Is a Modal Confirm Box Using JQuery Possible?

2019-01-16 14:13发布

Looked around quite a bit, and can't seem to find a JQuery solution (maybe its just a limitation of JavaScript) for this:

<a href="somelink.php" 
   onclick="return confirm('Go to somelink.php?');">Click Here</a>

In the above example, when a user clicks on the link, it will only go to its href if the user clicks OK in the confirm box.

What I am trying to do is get a more modern look using a popup div. Perhaps something like this:

<a href="somelink.php" 
   onclick="return jq_confirm('Go to somelink.php?');">Click Here</a>

(Where jq_confirm is a custom JQuery confirm function that pops up a nice div with a YES/NO or OK/CANCEL button pair).

However, I cannot seem to find any such thing.

I have looked at some JQuery widget libraries etc which offer similar functionality, but none will wait for the response from the user (at least, not in the scenario described above), but instead they just proceed and take the user to the link (or run any JavaScript embedded in the href='' piece of the link). I suspect this is because while you can attach a callback function to many of these widgets to return a true/false value, the onclick event does not wait for a response (callbacks are asynchronous), thereby defeating the purpose of the confirm box.

What I need is the same kind of halt-all-javascript (modal) functionality that the default confirm() command provides. Is this possible in JQuery (or even in JavaScript)?

As I am not an expert in JavaScript nor in JQuery, I defer to you gurus out there. Any JQuery (or even pure JavaScript) solution is welcome (if possible).

Thanks -

12条回答
甜甜的少女心
2楼-- · 2019-01-16 14:53

Almost three years later, I am looking for something similar. Since I have not found an acceptable "quick" solution, I wrote something that comes very close to the criteria of the OP. I figure others may find it useful in the future.

JavaScript is event-driven and that means it does not support any sort of "wait" or "sleep" loop that we can use to pause a pure-javascript confirm function. The options involve burning processor cycles, using a browser plugin, or AJAX. In our increasingly mobile world, and with sometimes spotty internet connections, none of these are great solutions. This means that we have to return from our "confirm" function immediately.

However, since there is no "false" logic in the code snippet above (ie. nothing is done when the user clicks "Cancel"), we can trigger the "click" or "submit" event again when the user clicks "OK." Why not set a flag and react based on that flag within our "confirm" function?

For my solution, I opted to use FastConfirm rather than a "modal" dialog. You can easily modify the code to use anything you want but my example was designed to use this:

https://github.com/pjparra/Fast-Confirm

Due to the nature of what this does, I do not see a clean way to package it up. If you feel that this has too many rough edges, feel free to smooth them out or rewrite your code the way that everyone else has recommended:

/* This version of $.fn.hasEvent is slightly modified to provide support for
 * the "onclick" or "onsubmit" tag attributes. I chose this because it was
 * short, even if it is cryptic.
 *
 * Learn more about the code by Sven Eisenschmidt, which is licensed under
 * the MIT and GPL at:
 *     http://github.com/fate/jquery-has-event
 */
(function($) {
    $.fn.hasEvent = function(A, F, E) {
        var L = 0;
        var T = typeof A;
        E = E ? E : this;
        var V = (E.attr('on'+A) != undefined);
        A = (T == 'string') ? $.trim(A) : A;
        if (T == 'function')
            F = A, A = null;
        if (F == E)
            delete(F);
        var S = E.data('events');
        for (e in S)
            if (S.hasOwnProperty(e))
                L++;
        if (L < 1)
            return V; // = false;
        if (A && !F) {
            return V = S.hasOwnProperty(A);
        } else if(A && S.hasOwnProperty(A) && F) {
            $.each(S[A], function(i, r) {
                if(V == false && r.handler == F) V = true;
            });
            return V;
        } else if(!A && F) {
            $.each(S, function(i, s) {
                if (V == false) {
                    $.each(s, function(k, r) {
                        if (V == false && r.handler == F)
                            V = true;
                    });
                }
            });
        }
        return V;
    }
    $.extend($, {hasEvent: $.fn.hasEvent});
}) (jQuery);

/* Nearly a drop-in replacement for JavaScript's confirm() dialog.
 * Syntax:
 *   onclick="return jq_confirm(this, 'Are you sure that you want this?', 'right');"
 *
 * NOTE: Do not implement "false" logic when using this function. Find another way.
 */
var jq_confirm_bypass = false;
function jq_confirm(el, question, pos) {
    var override = false;
    var elem = $(el);

    if ($.fn.fastConfirm == undefined) {
        override = confirm(question);
    } else if (!jq_confirm_bypass) {
        if (pos == undefined) {
            pos = 'right';
        }

        elem.fastConfirm({
            position: pos,
            questionText: question,
            onProceed: function(trigger) {
                var elem = $(trigger);
                elem.fastConfirm('close');

                if (elem.hasEvent('click')) {
                    jq_confirm_bypass = true;
                    elem.click();
                    jq_confirm_bypass = false;
                }
                if (elem.hasEvent('submit')) {
                    jq_confirm_bypass = true;
                    elem.submit();
                    jq_confirm_bypass = false;
                }
                // TODO: ???
            },
            onCancel: function(trigger) {
                $(trigger).fastConfirm('close');
            }
        });
    }

    return override ? override : jq_confirm_bypass;
}

So... onclick="return confirm('Do you want to test this?');" would become onclick="return jq_confirm(this, 'Do you want to test this?');" The pos/"right" parameter is optional and is specifically for Fast-Confirm.

When you click, the jq_confirm() function will spawn the jQuery dialog and return "false." When the user clicks "OK" then jq_confirm() sets a flag, calls the original click (or submit) event, returns "true", then unsets the flag in case you want to remain on the same page.

查看更多
Fickle 薄情
3楼-- · 2019-01-16 14:55

The following link has a jQuery plugin for confirm boxes similar to constructing like confirm("something") in JavaScript

http://labs.abeautifulsite.net/archived/jquery-alerts/demo/

查看更多
时光不老,我们不散
4楼-- · 2019-01-16 14:57

Put the redirect inside the function like:

<script>
    function confirmRedirect(url, desciption) {
       if (confirmWindow(desciption)) {
           window.location = url;
       }
    }
</script>

And call it like this:

<a href="javascript:confirmRedirect('somlink.php','Are you sure?')">Go!</a> 
查看更多
贼婆χ
5楼-- · 2019-01-16 14:58

I blogged about the solution to this issue here: http://markmintoff.com/2011/03/asp-net-jquery-confirm-dialog/

Even though the article is geared towards ASP.Net it can be easily adapted to php. It relies on preventing the click with a return false and when the user clicks "OK" or "YES" or what-have-you; the link or button is simply clicked again.

var confirmed = false;
function confirmDialog(obj)
{
    if(!confirmed)
    {
        $( "#dialog-confirm" ).dialog({
            resizable: false,
            height:140,
            modal: true,
            buttons: {
                "Yes": function()
                {
                    $( this ).dialog( "close" );
                    confirmed = true; obj.click();
                },
                "No": function()
                {
                    $( this ).dialog( "close" );
                }
            }
        });
    }

    return confirmed;
}

Give it a try and let me know what you think. I hope this solves your problem.

查看更多
干净又极端
6楼-- · 2019-01-16 15:02

I have a solution that can be used to replace the default window.confirm function. It doesn't require you overriding window.confirm as that is not fully possible.

My solution allows you to have a general class like me, let's say 'confirm-action' that you place on any element that requires a confirmation before being processed. The script is very simple and utilizes jQuery, jQuery UI Dialog and no other plugins.

You can find the complete demo of the implementation on jsFiddle, http://jsfiddle.net/74NDD/39/.

Usage:

  • Add this javascript code in your html head or before any other click binding you have in your javascript.

    $("#dialog:ui-dialog").dialog("destroy");
    
    $('.confirm-action').live('click', function(e) {
        $self = $(this);
    
        if (e && e.stopImmediatePropagation && $self.data('confirmed') !== true) {
            e.stopImmediatePropagation();
    
            $('#confirm-action-dialog').dialog({
                height: 110,
                modal: true,
                resizable: false,
                draggable: false,
                buttons: {
                    'Yes': function() {
                        $(this).dialog('close');
                        $self.data('confirmed', true);
                        $self.click();
                    },
                    'No': function() {
                        $self.data('confirmed', false);
                        $(this).dialog('close');
                    }
                }
            });
        } else if ($self.data('confirmed') === true) {
            e = window.event;
            e.cancelBubble = false;
            $self.data('confirmed', false);
        }
    
        return false;
    });
    
  • Place this html somewhere in the body (it is hidden by default).

    <div style="display:none;" id="confirm-action-dialog" title="Confirm Action?">
        <p>
            <span class="ui-icon ui-icon-alert"></span>
            Are you sure you want to continue?
        </p>
    </div>
    
  • Put the class 'confirm-action' on any element that requires confirmation.

    confirm-action

This solution works perfect as it does not alter jQuery event bubbling, it merely pauses (stops) all other events until the user decides what they want to do.

I hope this is helpful for someone else as I was unable to find any other solution that doesn't require me installing another jQuery plugin or do some other hack.

查看更多
仙女界的扛把子
7楼-- · 2019-01-16 15:05

My way around this problem was to add some arbitrary data to the object, and check for that data on click. If it existed, proceed with the function as normal, otherwise confirm with a yes/no (in my case using a jqtools overlay). If the user clicks yes - insert the data in the object, simulate another click and wipe the data. If they click no, just close the overlay.

Here is my example:

$('button').click(function(){
    if ($(this).data('confirmed')) {
        // Do stuff
    } else {
        confirm($(this));
    }
});

And this is what I did to override the confirm function (using a jquery tools overlay):

window.confirm = function(obj){
    $('#dialog').html('\
        <div>\
            <h2>Confirm</h2>\
            <p>Are you sure?</p>\
            <p>\
                <button name="confirm" value="yes" class="facebox-btn close">Yes</button>\
                <button name="confirm" value="no" class="facebox-btn close">No</button>\
            </p>\
        </div>').overlay().load();
    $('button[name=confirm]').click(function(){
        if ($(this).val() == 'yes') {
            $('#dialog').overlay().close();
            obj.data('confirmed', true).click().removeData('confirmed');
        } else {
            $('#dialog').overlay().close();
        }
    });
}
查看更多
登录 后发表回答