【问题标题】:How do I explicitly execute default action from jQuery event如何从 jQuery 事件显式执行默认操作
【发布时间】:2011-11-12 15:57:22
【问题描述】:

this question 开始,我正在尝试实现一个不显眼的确认对话框。

$(document).ready(function () {
    $("[data-confirmPrompt]").click(function (event) {
        var confirmPrompt = event.currentTarget.attributes['data-confirmPrompt'].value;
        event.preventDefault();
        $.prompt(confirmPrompt, {
            buttons: { Yes: true, No: false },
            callback: function (v, m, f) {
                if (v) {
                    // User clicked Yes.  Unbind handler to avoid
                    // recursion, then click the target element again
                    $(event.currentTarget).unbind('click');
                    event.currentTarget.click();
                }
            }
        });
    });
});

当用户单击“是”时,我希望执行与事件关联的默认操作。我已经通过取消绑定 jQuery 处理程序并再次单击该元素来完成它。这在提交表单或导航到不同页面时工作正常 - 但当然不适用于启用 AJAX 的页面,我想保留 jQuery 事件处理程序。

是否有其他通用方式来执行默认操作?逻辑上类似于event.executeDefault()

【问题讨论】:

  • 一些想法。 1. 让你的插件“包装”事件处理程序:$('[data-confirmPrompt]').prompt('click', function() { ... }),然后你可以轻松地解除绑定和重新绑定一个特定的事件处理程序触发对话框。
  • 2.在元素上设置一个特殊值,以防止第二次触发提示。在点击处理程序的顶部: if ($(this).data('your-flag')) { $(this).data('your-flag', 0);返回真; }。在回调中设置 data('your-flag', true) ,完全不需要解绑点击事件。
  • @Alexey - 谢谢,我一直在考虑您的解决方案 2 - 使用我们过去经常使用的标志来防止重新进入 VB 事件处理程序。如果没有人想出更优雅的东西,我可能会选择它。
  • 显然这个问题已经很老了,但是为了后代,这里有一个建议。使用.on('click',.off('click') 而不是.click.unbind('click')。然后为事件添加一个命名空间,如下所示:.on('click.confirm',。然后,在删除处理程序时,使用相同的命名空间——.off('click.confirm')。这只会解除您刚刚注册的处理程序的绑定,而不是所有的 jquery 处理程序——怀疑您的 Ajax 调用仍然可以工作。这应该从 jquery 1.7 开始工作。
  • 我认为这样做的方法是防止事件冒泡(event.stopPropagation(),然后是return true

标签: jquery events


【解决方案1】:

使用 Alexey Lebedev 在他的第二条评论中提出的建议,我当前的实现现在看起来像下面的示例,除了我还为按钮标签添加了我自己的本地化实现。

注意事项:

  • 我现在正在使用 jqueryUI 对话框小部件
  • 注意 .delegate 的使用,以便处理程序是“ajax-aware”的,即在页面加载后添加到 DOM 的元素上工作,例如作为 AJAX 调用的结果
  • 当用户在确认对话框中单击“是”时,使用一个标志来防止递归。
  • 使用 jquery 1.6.4 和 jquery-ui-1.8.16

如果有人可以提出改进建议,请加入。

<!-- Examples of usage -->
<input type='submit' data-confirm="OK to delete customer 123?" ... />
<a href="..." data-confirm="OK to navigate?" ... />

<!-- Implementation -->
<script type="text/javascript">
    var confirmClickHandler = function (event) {
        if ($(event.currentTarget).data('isConfirming')) return;
        var message = event.currentTarget.attributes['data-confirm'].value;
        event.preventDefault();
        $('<div></div>')
                .html(message)
                .dialog({
                    title: "Confirm",
                    buttons: {
                        "Yes": function () {
                            $(this).dialog("close");
                            $(event.currentTarget).data('isConfirming', true);
                            event.currentTarget.click();
                            $(event.currentTarget).data('isConfirming', null);
                        },
                        "No": function () {
                            $(this).dialog("close");
                        }
                    },
                    modal: true,
                    resizable: false,
                    closeOnEscape: true
                });
    };

    $(document).ready(function () {
        $("body").delegate("[data-confirm]", "click", confirmClickHandler);
    });
</script>

【讨论】:

    【解决方案2】:

    我正在做类似的事情,这对我来说很好:

    $('#link').click(function(e){
        if(!confirm('Are you sure you want to asdf?')){
            e.preventDefault();
        }
    });
    

    【讨论】:

    • 是的,这可行,但 javascript 确认的问题是,只要显示它,用户就无法与选项卡式浏览器上的任何其他选项卡进行交互。我使用的 jQuery 提示是当前页面的模态,但用户仍然可以切换到其他选项卡。
    • @Joe 这是一个您不必担心的问题。有些浏览器实际上并没有这样做(我认为 iOS 没有)。
    • 如果你想添加一个格式化的段落来确认,并且用户必须在回复是或否之前阅读??
    【解决方案3】:

    老实说,我不知道这是否能回答你的问题,但它可能会有所帮助。

    考虑以下 HTML:

    <button onclick="alert('Hello world!');" class="btn">Test 1</button>
    <button onclick="alert(this.className);" class="btn">Test 2</button>
    

    我已将以下内容添加到我的$(document).ready

    $('button').each(function() {
        var btn = $(this);
        var onClick = btn.attr('onclick');
    
        //replace this with _this
        onClick = onClick.replace(/this/g, "_this");
    
        btn.attr('onclick', '');
    
        btn.click(function() {
            if (confirm('Do it?')) {
    
                //set _this first!
                var _this = btn[0];
    
                eval(onClick);
            }
        });
    });
    

    它似乎完成了工作。检查这个 jsFiddle 示例:http://jsfiddle.net/KeesCBakker/4jThg/

    编辑
    我创建了一些看起来更像你的问题的东西:http://jsfiddle.net/KeesCBakker/hqLH5/。只是不知道您使用的是哪个 $.prompt 插件,所以我从github 中找到了第一个插件(这个插件仅适用于 Chrome :S)。

    【讨论】:

    • 您的解决方案似乎专门处理 onclick 处理程序的确认 - 我正在寻找更通用的东西,所以它并没有真正回答这个问题。请参阅我自己的答案,了解迄今为止我提出的最佳解决方案。
    【解决方案4】:

    我能够通过从更具体的上下文调用 event.stopPropagation() 并确保我调用 event.preventDefault() 来实现这一点。虽然您不能显式地调用默认操作,但您可以设置条件以使默认操作发生 - 并根据您的意愿执行尽可能少或尽可能多的其他操作。

        // Normal event handler
        $("[data-toggle]").click(ev => {
          switchToTab(ev.currentTarget)
          ev.preventDefault()
        })
    
        // Allow default handler in a specific case.
        $("[data-toggle] ul a").click(ev => {
          // Don't bubble the event to the less specific handler, above
          ev.stopPropagation()
          // An incorrect return value will also cancel the default action.
          return true
        })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-13
      • 1970-01-01
      • 2011-07-08
      • 2011-08-14
      • 2015-06-11
      相关资源
      最近更新 更多