繁体   English   中英

阻止页面在beforeunload事件处理程序中卸载

[英]Stop page from unloading within the beforeunload event handler

在用户浏览页面代码之前,请检查他是否编辑了某些表单字段。 如果他这样做了,我将显示一个带有“ Yes和“ No按钮的模态窗口。 如果他单击否,则应该关闭模式对话框,并且用户仍留在该窗口中。 如果是,请保存并卸载。

  $(window).bind('beforeunload', function(){
        // check if any field is dirty 
        if ($('div.form').dirtyForms('isDirty')) {
            var modalParams = {
                Content: 'You have some unsaved changes, proceed?'
                OnSave: navigateAndSave,
                OnCancel: cancelNavigate
            }
           ShowModal(modalParams);
        }
    })

function navigateAndSave() {
    // Do stuff
};

function cancelNavigate() {
    // Stop page from unloading and close the modal
};

那么,在cancelNavigate我可以做什么来阻止页面的卸载呢?

这是可行的,但前提是用户单击页面内的超链接。 如果用户使用浏览器离开页面,他们将获得默认的浏览器对话框,该对话框没有保存选项。

脏表单会自动附加(并删除处理程序)到beforeunload事件,因此您尝试创建另一个事件处理程序的尝试肯定会失败。 使用脏表单时,绝对不要这样做。

您没有提到要使用哪种模式对话框框架,因此我将仅显示一个使用jQuery UI对话框的示例。 集成其他对话框框架是相似的。 为此,您可能需要检出现有预建对话框的源代码。

另外,您的用例有点短。 如果用户想离开并忽略更改怎么办? 我添加了一个示例,其中包括一个用于执行此操作的附加选项。

<html>
<head>
    <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/jquery.ui/1.11.3/jquery-ui.min.css" />
</head>
<body>

    <script type="text/javascript" src="//cdn.jsdelivr.net/g/jquery@1.11.3,jquery.ui@1.11.3,jquery.dirtyforms@2.0.0"></script>
    <script type="text/javascript">
    $(document).ready(function() {
        // This is required by jQuery UI dialog
        $('body').append('<div id="dirty-dialog" style="display:none;" />');

        // This must be called before the first call to .dirtyForms
        $(document).bind('bind.dirtyforms', function (ev, events) {
            var originalOnRefireClick = events.onRefireClick;

            events.onRefireClick = function (ev) {
                if (saveForm) {
                    // TODO: Replace this with your AJAX function
                    // to save the form.
                    alert('saving form...');
                }
                originalOnRefireClick(ev);
            };
        });

        // Flag indicating whether or not to save the form on close.
        var saveForm = false;

        $('.mainForm').dirtyForms({
            dialog: {
                // Custom properties to allow overriding later using 
                // the syntax $.DirtyForms.dialog.title = 'custom title';

                title: 'Are you sure you want to do that?',
                proceedAndSaveButtonText: 'Save Changes & Continue',
                proceedAndCancelButtonText: 'Cancel Changes & Continue',
                stayButtonText: 'Stay Here',
                preMessageText: '<span class="ui-icon ui-icon-alert" style="float:left; margin:2px 7px 25px 0;"></span>',
                postMessageText: '',
                width: 650,

                // Dirty Forms Methods
                open: function (choice, message) {
                    $('#dirty-dialog').dialog({
                        open: function () {
                            // Set the focus on close button. This takes care of the 
                            // default action by the Enter key, ensuring a stay choice
                            // is made by default.
                            $(this).parents('.ui-dialog')
                                   .find('.ui-dialog-buttonpane button:eq(2)')
                                   .focus();
                        },

                        // Whenever the dialog closes, we commit the choice
                        close: choice.commit,
                        title: this.title,
                        width: this.width,
                        modal: true,
                        buttons: [
                            {
                                text: this.proceedAndSaveButtonText,
                                click: function () {
                                    // Indicate the choice is the proceed action
                                    choice.proceed = true;

                                    // Pass a custom flag to indicate to save the data first
                                    // in the onRefireClick event
                                    saveForm = true;

                                    $(this).dialog('close');
                                }
                            },
                            {
                                text: this.proceedAndCancelButtonText,
                                click: function () {
                                    // Indicate the choice is the proceed action
                                    choice.proceed = true;
                                    // Pass a custom flag to indicate not to save the data
                                    // in the onRefireClick event
                                    saveForm = false;

                                    $(this).dialog('close');
                                }
                            },
                            {
                                text: this.stayButtonText,
                                click: function () {
                                    // We don't need to take any action here because
                                    // this will fire the close event handler and
                                    // commit the choice (stay) for us automatically.
                                    $(this).dialog('close');
                                }
                            }
                        ]
                    });

                    // Inject the content of the dialog using jQuery .html() method.
                    $('#dirty-dialog').html(this.preMessageText + message + this.postMessageText);
                },
                close: function () {
                    // This is called by Dirty Forms when the 
                    // Escape key is pressed, so we will close
                    // the dialog manually. This overrides the default
                    // Escape key behavior of jQuery UI, which would
                    // ordinarily not fire the close: event handler 
                    // declared above.
                    $('#dirty-dialog').dialog('close');
                }
            }
        });
    });
    </script>

    Change one of the fields below, then click "Go to Google" to try to navigate away.

    <form class="mainForm" action="jqueryui.html">
        First name: <input type="text" name="fname"><br>
        Last name: <input type="text" name="lname"><br>
        <input type="submit" value="Submit">
    </form>

    <a href="http://www.google.com/">Go to Google</a>

</body>
</html>

该示例使用自定义事件绑定来附加到onRefireClick事件处理程序,该事件处理程序在choice.proceed = true时被激发,而在falsechoice.proceed = true被激发。

那不可能

您只能显示短信以及继续在页面上显示或消失的选项。

请查看此链接以获取更多信息: https : //developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload

 window.onbeforeunload = funcRef 
  • funcRef是对函数或函数表达式的引用。
  • 该函数应为Event对象的returnValue属性分配一个字符串值,并返回相同的字符串。

例:

 window.onbeforeunload = function(e) { return 'Dialog text here.'; }; 

在用户决定保留在页面上之后,您可以显示您的模态,但是我认为建议那时会失败。

如其他人所述,您可以通过侦听页面上链接和表单上的单击和按键事件来拦截导航,但是当用户尝试手动输入URL,关闭标签,关闭导航栏时,这将不允许您显示任何对话框。窗口,按下重新加载,后退或前进按钮等。

beforeunload事件是通过这种方式设计的,可以保护用户免受恶意脚本的攻击。

如果允许这种控制,则有人可以将您的浏览器锁定在所需的页面中,而不允许您浏览或关闭窗口。

编辑。:

通过附加到2个事件beforeunloadunload我设法显示了一个确认对话框,其工作原理几乎与您想要的相同。 它适用于Windows的Internet Explorer 11,Firefox 40和Safari 5.1(我现在可以确认):

 var alreadyTriggered = false; function onQuit() { if (alreadyTriggered) return true; alreadyTriggered = true; if (confirm('Sure?')) { alert('OK'); } else { alert('Cancel'); } } window.onbeforeunload = onQuit; window.onunload = onQuit; 
 You can <a href="javascript: location.reload();">reload the page</a> to test it here. 

这依赖于确认对话框导致的JS事件循环的中断,并且无法使用自定义对话框来完成此工作,因为页面将在用户有机会与之交互之前更改或关闭。

仍然无法避免页面更改或关闭,也无法在Chrome中实现此功能。 如果用户交互未触发该事件,则在Firefox中也将不起作用。

我相信您只需要在事件上调用preventDefault。

 $(window).bind('beforeunload', function(e){
        // check if any field is dirty 
        if ($('div.form').dirtyForms('isDirty')) {
            var modalParams = {
                Content: 'You have some unsaved changes, proceed?'
                OnSave: navigateAndSave,
                OnCancel: e.preventDefault();
            }
           ShowModal(modalParams);
        }
    })

function navigateAndSave() {
    // Do stuff
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM