javascript可以从一个单独的方法监听确认对话的结果

Can javascript listen for the result of a confirm dialogue from a separate method?

本文关键字:方法 单独 监听 确认 结果 对话 一个 javascript      更新时间:2023-09-26

我知道只有当确认对话框在函数中进行确认时,JS才采取通常的操作方式,比如这个jQuery示例:

<script type="text/javascript">
  $(function () {
    $("#dropdown").change(function () {
      var success = confirm('Are you sure want to change the Dropdown ????');
      if (success == true) {
        // do something                  
      }
      else {
        // Cancel the change event and keep the selected element
      }
    });
  });
</script>

这在我的情况下不起作用,因为确认是Rails助手的一部分:

<%= link_to "Delete", {:controller => 'foo', :action => 'delete', :id => @item.id},
  {:method => :post, :confirm => "Are you sure?", :class => "start_spinner"} %>

我想在点击时运行一些javascript(隐藏链接以防止点击两次),但前提是确认为真。不幸的是,至少在Rails 2.3.x中,当存在:method:confirm选项时,不可能使用:onclick。(此行为在ApiDock上针对link_to助手进行了说明,在我的应用程序中也是如此。)

编辑:我认为我包含了ApiDock中的示例而不是我的确切代码,这造成了一些混乱。很抱歉。我修改了下面的代码,以反映Rails在包含:method => :post选项时的行为,因为它必须在我的代码中。两种输出之间的区别仍然只是放弃了destroyJsFunction方法,但onclick中确实发生了一大堆其他事情,这些事情似乎干扰了Sukima和agnoster提出的解决方案的实现。

<%= link_to "Delete", {:controller => 'foo', :action => 'delete', :id => @item.id}, :method => :post, :confirm=>"Are you sure?", :onclick=>"destroyJsFunction()", :class => "start_spinner" %>
# expected output
# => <a href="/foo/delete/1" class='start_spinner' onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'CSRF_TOKEN'); f.appendChild(s);f.submit(); }; {destroyJsFunction()}; return false;">Delete</a>
# actual output
# => <a href="/foo/delete/1" class='start_spinner' onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'CSRF_TOKEN'); f.appendChild(s);f.submit(); }; return false;">Delete</a>

结束编辑

因为我使用Rails提交POST请求,所以我不能只是用纯HTML重写链接。

我想在点击start_spinner类的链接时运行我的javascript,但如果确认为false,我找不到重新显示链接的方法。有没有办法让一个单独的javascript监听确认对话的结果?

所有确认所做的就是在HTML中放置一些JavaScript,这正是你所描述的:提示用户,然后在成功响应时提交表单。

如果你想做一些不同的事情,那么你必须编写自己的确认方法。由于逻辑如此简单,我相信rails团队认为,如果你想要更多,你可以自己写。

制作一个执行确认和if/else逻辑的函数。我会使用我自己的不引人注目的JS,比如使用jQuery来附加点击事件,但你也可以像上面提到的那样使用rails link_to helper选项:onclick(我个人讨厌这个选项。)

jQuery示例:

$(function() {
  $('a.destroy').on('click', function(e) {
    e.preventDefault();
    var $el      = $(this);
    var response = confirm($el.data('confirm') || 'Are you sure?');
    if (!response) { return; }
    $el.css({'pointer-events': 'none'});
    $.ajax({
      url:  $el.attr('href'),
      type: 'DELETE',
      data: {_method: 'delete'}
    })
    .then(function() {
      alert('Deleted! we should do something here');
    })
    .fail(function() {
      alert('Opps, it didn''t delete, check the respose to see why.');
    })
    .always(function() {
      $el.css({'pointer-events': 'auto'});
    });
  });
  // Only for SO example not needed for real code
  $('#reset').on('click', function(e) {
    e.preventDefault();
    $('a').css({'pointer-events': 'auto'});
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#/path/with/:id" class="destroy" data-confirm="Are your sure?">Confirm?</a>
(<a href="#" id="reset" title="this is not need in real code">reset</a>)

简短的回答:有点,有点,但有点古怪。

所以你想知道点击链接是否被确认。从其他地方判断的唯一方法(不需要注入回调,这听起来像是Rails的问题)是捕获事件并检查是否阻止了默认操作(这就是return confirm()在这里所做的)。

使用jQuery,您可以在页面中添加一些JS,如下所示:

$('#confirm-link').click(function(e) {
  if (e.isDefaultPrevented()) {
    alert("I feel rejected")
  } else {
    alert("I feel confirmed")
  }
})

我摆弄着JSFiddle。不过它会有点脆。

如果将删除链接触发为Ajax调用,则可以在确认对话框后呈现一个可以处理显示的js.erb文件。例如:

视图中的AJAX触发器:

<li id="post_<%= post.id %>">
  <%= link_to "Delete", post_path(post), method: :delete, data: { confirm: "Are you sure you want to remove this post?" }, remote: true %>
</li>

控制器:

# app/controller/posts_controller.rb
class PostsController < ApplicationController
  def destroy
    @post = Post.find(params[:id])
    @post.destroy
  end
end

渲染视图:

# app/views/posts/destroy.js.erb
$('#post_<%= @post.id %>').hide()

如果您正在使用Rails UJS的data-confirm,并且希望根据确认是否为true来运行一些自定义脚本,请使用confirm:complete事件:

= link_to "#", data: { confirm: "Are you sure?"}, class: "btn-remove" do

JS:

$('.list').on('confirm:complete', '.btn-remove', function removeCallback(ev, answer) {
  if (answer) { 
    // Remove some element
  }
  return false; // prevents jumping to top of page.
});