jquery.dirtyforms icon indicating copy to clipboard operation
jquery.dirtyforms copied to clipboard

Dialog

Open jordanbaucke opened this issue 8 years ago • 8 comments

I'm trying to get the dialogs example to work, but I'm always getting the default dialog back?

I see there is also a SO question that was unanswered about a similar issue? https://stackoverflow.com/questions/15617322/cant-get-custom-dialog-to-work-with-dirtyforms

Any advice? I get no javascript errors. I've added the concatenated file and already had jQuery UI loaded into my page.

Thanks

jordanbaucke avatar Feb 20 '16 08:02 jordanbaucke

Thanks for the report.

However, there isn't much help we can provide unless you post the code (relevant HTML and JavaScript) you are using that is causing an issue. The StackOverflow issue that you linked to is using version 1.x, so that code will no longer work if you are using version 2.x.

Do note that there is a drop-in dialog module for jQuery UI that is compatible with all versions of Dirty Forms, you only need to use custom code if you need to customize the dialog in some way that is not supported by the module's options.

Also note that the custom dialog only functions if the user clicks a hyperlink on the page. When the user tries to navigate away using the browser controls, the browser dialog is shown (there is no way to override that behavior in JavaScript).

NightOwl888 avatar Feb 20 '16 21:02 NightOwl888

Ok, here is the JS I'm using (the form is generated from a mark-up, Visualforce so it's too much to post here, the rest of the functionality works fine, ignoreClass, etc.)

<script type="text/javascript" src="//cdn.jsdelivr.net/g/[email protected],[email protected],[email protected](jquery.dirtyforms.min.js+jquery.dirtyforms.dialogs.jquery-ui.min.js)"></script>
<script type="text/javascript">
$(document).ready(function() {
        $('body').append('<div id="dirty-dialog" style="display:none;" />');
        var dialogElement = {
            // Custom properties to allow overriding later using 
            // the syntax $.DirtyForms.dialog.title = 'custom title';

            title: 'Are you sure you want to do that?',
            proceedButtonText: 'Leave This Page',
            stayButtonText: 'Stay Here',
            preMessageText: '<span class="ui-icon ui-icon-alert" style="float:left; margin:2px 7px 25px 0;"></span>',
            postMessageText: '',
            width: 430,

            // 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(1)')
                               .focus();
                    },

                    // Whenever the dialog closes, we commit the choice
                    close: choice.commit,
                    title: this.title,
                    width: this.width,
                    modal: true,
                    buttons: [
                        {
                            text: this.proceedButtonText,
                            click: function () {
                                // Indicate the choice is the proceed action
                                choice.proceed = true;
                                $(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');
            }
        };

        $('.mainForm').dirtyForms({
            dialog: dialogElement,
            message: 'There are unsaved evidence changes, please click "Save Evidence" or your changes will be lost.',
            ignoreSelector: '.ignore'
        });
});
</script>

Pretty straight forward, I've also tried defining it directly inside of the call. And as the $.DirtyForms.dialog = {...} to no result?

jordanbaucke avatar Feb 21 '16 06:02 jordanbaucke

The code you have posted works as-is. Here it is again in a very simple HTML file.

<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/[email protected],[email protected],[email protected](jquery.dirtyforms.min.js+jquery.dirtyforms.dialogs.jquery-ui.min.js)"></script>
    <script type="text/javascript">
    $(document).ready(function() {
            $('body').append('<div id="dirty-dialog" style="display:none;" />');
            var dialogElement = {
                // Custom properties to allow overriding later using 
                // the syntax $.DirtyForms.dialog.title = 'custom title';

                title: 'Are you sure you want to do that?',
                proceedButtonText: 'Leave This Page',
                stayButtonText: 'Stay Here',
                preMessageText: '<span class="ui-icon ui-icon-alert" style="float:left; margin:2px 7px 25px 0;"></span>',
                postMessageText: '',
                width: 430,

                // 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(1)')
                                   .focus();
                        },

                        // Whenever the dialog closes, we commit the choice
                        close: choice.commit,
                        title: this.title,
                        width: this.width,
                        modal: true,
                        buttons: [
                            {
                                text: this.proceedButtonText,
                                click: function () {
                                    // Indicate the choice is the proceed action
                                    choice.proceed = true;
                                    $(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');
                }
            };

            $('.mainForm').dirtyForms({
                dialog: dialogElement,
                message: 'There are unsaved evidence changes, please click "Save Evidence" or your changes will be lost.',
                ignoreSelector: '.ignore'
            });
    });
    </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>

However, you are including 2 dialog modules, one from the CDN and one in code, which is not allowed. You can reduce your code to the following, and it still works.

<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/[email protected],[email protected],[email protected](jquery.dirtyforms.min.js+jquery.dirtyforms.dialogs.jquery-ui.min.js)"></script>
    <script type="text/javascript">
    $(document).ready(function() {
            $('.mainForm').dirtyForms({
                message: 'There are unsaved evidence changes, please click "Save Evidence" or your changes will be lost.',
                ignoreSelector: '.ignore'
            });
    });
    </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>

NightOwl888 avatar Feb 21 '16 07:02 NightOwl888

FYI - I have posted an example on StackOverflow how to make a save & continue dialog like in your example. In that case, you will need to customize the dialog a little, so you should not add the reference to the jquery.dirtyforms.dialogs.jquery-ui module from the CDN.

NightOwl888 avatar Feb 21 '16 17:02 NightOwl888

@NightOwl888 great thank you.

In digging in a bit, I've discovered that what is happening for for me at least, is that immediately before the dialog is displayed, in the bindFn, I'm getting an eventType == "beforeunload", which is trigging the standard message, as opposed to falling through, and showing the dialog.

If I comment this out:

if (eventType == 'beforeunload') {
            dirtylog('Returning to beforeunload browser handler with: ' + dirtyForms.message);
            return dirtyForms.message;
        }
        if (!dirtyForms.dialog) return;

I get the dialog, but the next two lines:

// Using the GUI dialog...
        ev.preventDefault();
        ev.stopImmediatePropagation();

Doesn't stop the page the URL from changing when I follow a link on my page?

jordanbaucke avatar Feb 22 '16 23:02 jordanbaucke

My best guess is that your anchor is being ignored by Dirty Forms and as a result it is firing the beforeunload event. Normally, an anchor tag's event will be cancelled by Dirty Forms before it gets that far.

Do you have any JavaScript attached to the anchor's click event? It might help if you post that code. If you are doing a redirect in JavaScript or as a meta refresh, it might be causing the issue.

It would also help if you could confirm/deny whether the examples I have provided work in your environment.

Of course, the best way to determine what is happening is to provide a standalone HTML document or JSFiddle that demonstrates the issue so I can analyze it. Other than that I can only guess what is happening.

NightOwl888 avatar Feb 23 '16 19:02 NightOwl888

Were you able to find a solution to this issue? If not, posting a complete example might help.

NightOwl888 avatar Mar 08 '16 19:03 NightOwl888

Not sure what browser the OP is using but... https://developers.google.com/web/updates/2016/04/chrome-51-deprecations?hl=en

Remove Custom Messages in onbeforeload Dialogs TL;DR: A window’s onbeforeload property no longer supports a custom string.

Intent to Remove | Chromestatus Tracker | Chromium Bug

A window’s onbeforeunload property may be set to a function that returns a string that is shown to the user in a dialog box to confirm that the user wants to navigate away. This was intended to prevent users from losing data during navigation. Unfortunately, it is often used to scam users.

Starting in Chrome 51, a custom string will no longer be shown to the user. Chrome will still show a dialog to prevent users from losing data, but it’s contents will be set by the browser instead of the web page.

With this change, Chrome will be consistent with Safari 9.1 and later, as well as Firefox 4 and later.

KrunchMuffin avatar Aug 09 '16 13:08 KrunchMuffin