Javascript Rails 3数据确认属性的jQuery UI对话框,而不是alert()
在Rails 3中,将:confirm参数传递给link_to将填充链接的数据确认属性。这将在单击链接时引发JS警报() 我使用的是rails jQuery UJS适配器()。rails.js中的相关代码是:Javascript Rails 3数据确认属性的jQuery UI对话框,而不是alert(),javascript,jquery,ruby-on-rails,unobtrusive-javascript,Javascript,Jquery,Ruby On Rails,Unobtrusive Javascript,在Rails 3中,将:confirm参数传递给link_to将填充链接的数据确认属性。这将在单击链接时引发JS警报() 我使用的是rails jQuery UJS适配器()。rails.js中的相关代码是: $('body').delegate('a[data-confirm], button[data-confirm], input[data-confirm]', 'click.rails', function () { var el = $(this); if (el.tr
$('body').delegate('a[data-confirm], button[data-confirm], input[data-confirm]', 'click.rails', function () {
var el = $(this);
if (el.triggerAndReturn('confirm')) {
if (!confirm(el.attr('data-confirm'))) {
return false;
}
}
});
及
我想知道如何修改它以生成jQuery对话框(例如),允许用户确认或取消
我对JavaScript的了解不足以优雅地实现这一点。我目前的方法是简单地重写$('body').delegate()函数,而不是实例化一个lightbox。但是,我认为有一种比这更有效的方法。我不明白为什么在JavaScript confirm()函数仍然可以正常工作的情况下,您需要使用jQuery对话框。我会这样做:
$('a[data-confirm]').click(funciton() {
confirm($(this).data("confirm"));
});
$.rails.allowAction = function(element) {
var message = element.data('confirm'),
answer = false, callback;
if (!message) { return true; }
if ($.rails.fire(element, 'confirm')) {
myCustomConfirmBox(message, function() {
callback = $.rails.fire(element,
'confirm:complete', [answer]);
if(callback) {
var oldAllowAction = $.rails.allowAction;
$.rails.allowAction = function() { return true; };
element.trigger('click');
$.rails.allowAction = oldAllowAction;
}
});
}
return false;
}
function myCustomConfirmBox(message, callback) {
// implement your own confirm box here
// call callback() if the user says yes
}
如果你想使用一个对话框,它有点不同。您可以一次性创建所需的每个对话框,也可以在应用程序范围内采用统一的方法,以便rails.js或application.js可以处理任何对话框实例。例如,您的页面上需要这样的内容:
<a class="dialogLauncher">The link that creates your dialog</a>
<div class="dialog" title="My confirmation title" style="display:none">
<p>My confirmation message</p>
</div>
如果您想进一步自定义对话框,请签出
编辑
现在我想到了这一点,这将是一个定制表单生成器的好机会。当某个属性存在时,您可以覆盖其中一个Rails链接标记以输出类似于上面列出的html,即:dialog=>true
。这肯定是一种很有讽刺意味的方式。您还可以在标记中添加其他选项,如对话框标题等
编辑
更好的是,不要像通常那样使用
:dialog=>true
,而是使用:confirm=>“我的确认消息”
,但是在覆盖link\u to时,您将使用:confirm
选项创建jQuery需要的对话框html,删除该选项,然后调用super
,这就是我让它工作的方法。请提出任何更正/改进建议
#
在rails.js中
// Added new variable
var deleteConfirmed = false;
// Changed function to use jquery dialog instead of confirm
$('body').delegate('a[data-confirm], button[data-confirm], input[data-confirm]', 'click.rails', function () {
var el = $(this);
/*
if (el.triggerAndReturn('confirm')) {
if (!confirm(el.attr('data-confirm'))) {
return false;
}
}
*/
if (el.triggerAndReturn('confirm')) {
if(deleteConfirmed) {
deleteConfirmed = false;
return true;
}
$( "#dialog-confirm" ).dialog("option", "buttons",
{
"Delete": function() {
$( this ).dialog( "close" );
deleteConfirmed = true;
el.trigger('click');
return true;
},
Cancel: function() {
$( this ).dialog( "close" );
return false;
}
}
);
$( "#dialog-confirm" ).dialog("open");
return false;
}
});
#
#
在application.js中
//Ensure confirm Dialog is pre-created
jQuery(function () {
$( "#dialog-confirm" ).dialog({
autoOpen: false,
resizable: false,
height:140,
modal: true
});
});
#
#
在layout.html中
Alt您可以将此div放置在生成的html中的任何位置
<div id='dialog-confirm' title='Confirm Delete'>
<p>
<span class='ui-icon-alert' style='float:left; margin:0 7px 20px 0;'>
This item will be permanently deleted. Are you sure?
</span>
</p>
</div>
#
此项目将被永久删除。你确定吗?
我刚刚为Rails jquery ujs添加了一个外部API,以实现这种定制。现在,您可以通过插入(并重新写入)函数$.rails.allowAction
使rails.js使用自定义确认对话框
请参阅我的文章,以获取带有示例的完整解释
编辑:从开始,我将确认
对话框功能移动到$.rails
对象,以便现在可以更轻松地修改或替换它。例如
$.rails.confirm = function(message) { return myConfirmDialog(message); };
正如其他人所提到的,您不能使用jQuery对话框,因为
$.rails.confirm
需要阻止,直到它返回用户的答案
但是,您可以在应用程序.js
文件中覆盖$.rails.allowAction
,如下所示:
$('a[data-confirm]').click(funciton() {
confirm($(this).data("confirm"));
});
$.rails.allowAction = function(element) {
var message = element.data('confirm'),
answer = false, callback;
if (!message) { return true; }
if ($.rails.fire(element, 'confirm')) {
myCustomConfirmBox(message, function() {
callback = $.rails.fire(element,
'confirm:complete', [answer]);
if(callback) {
var oldAllowAction = $.rails.allowAction;
$.rails.allowAction = function() { return true; };
element.trigger('click');
$.rails.allowAction = oldAllowAction;
}
});
}
return false;
}
function myCustomConfirmBox(message, callback) {
// implement your own confirm box here
// call callback() if the user says yes
}
它的工作原理是立即返回
false
,从而有效地取消单击事件。然而,然后,您的自定义函数可以调用回调函数来实际跟踪链接/提交表单。我喜欢@Marc Schütz关于重写$.rails.allowAction的回答。allowAction是我在网上找到的大部分内容,但我不太喜欢重写allowAction
中的功能,因为它在整个过程中都在使用jquery ujs代码库(如果有副作用呢?或者如果该方法的源在将来的更新中更改呢?)
到目前为止,最好的方法是使$.rails.confirm
返回一个承诺。。。但是:(
所以…我推出了我自己的方法,我认为这是值得一提的,因为它比上面概述的方法更轻。它不会劫持allowAction
。这里是:
# Nuke the default confirmation dialog. Always return true
# since we don't want it blocking our custom modal.
$.rails.confirm = (message) -> true
# Hook into any data-confirm elements and pop a custom modal
$(document).on 'confirm', '[data-confirm]', ->
if !$(this).data('confirmed')
myCustomModal 'Are you sure?', $(this).data('confirm'), =>
$(this).data('confirmed', true)
$(this).trigger('click.rails')
false
else
true
# myCustomModal is a function that takes (title, message, confirmCallback)
它是如何工作的?如果您查看,您会注意到如果确认事件
返回错误值,allowAction
方法将停止。因此流是:
用户单击带有数据确认
属性的链接或按钮。链接或按钮上没有数据确认
,因此我们进入第一个if块,触发自定义模式并返回false,从而停止ujs单击处理程序中的继续操作
用户在自定义模式中确认,并触发回调。我们通过数据('confirmed',true)
在元素上存储状态,并重新触发先前触发的相同事件(单击.rails
)
这一次,confirm事件
将落入else
块(因为data('confirled')
为真)并返回真,导致allowAction
块计算为真
我确信我甚至错过了其他可能使这更简单的方法,但我认为这是一种非常灵活的方法,可以在不破坏核心jquery ujs
功能的情况下获得自定义确认模式
(另外,因为我们正在使用.on()
这将在加载时或将来绑定到页面上的任何数据确认元素,这与.delegate()
的工作方式类似,以防您感到奇怪。)这就是我解决此问题的方法。
我尝试了很多不同的方法,但只有这一种有效
在rails.js中
function myCustomConfirmBox(element, callback) {
const modalConfirmDestroy = document.getElementById('modal-confirm');
// wire up cancel
$("#modal-confirm #cancel-delete").click(function (e) {
e.preventDefault();
modalConfirmDestroy.classList.remove('modal--open');
});
// wire up OK button.
$("#modal-confirm #confirm-delete").click(function (e) {
e.preventDefault();
modalConfirmDestroy.classList.remove('modal--open');
callback(element, true);
});
// show the dialog.
modalConfirmDestroy.classList.add('modal--open');
}
在这里,我使用了@Mark G.的代码,但做了一些修改。因为代码中剪掉的$(this.trigger('click.rails')对我不起作用
$.rails.confirm = function(message) {return true};
$(document).on('confirm', '[data-confirm]', (event)=> {
if (!$(this).data('confirmed'))
{
myCustomConfirmBox($(this), (element, choice)=> {
element.data('confirmed', choice);
let clickedElement = document.getElementById(event.target.id);
clickedElement.click();
});
return false;
}
else
{
return true;
}
});
然后在html.erb文件中,我有以下链接代码:
<%= link_to "documents/#{document.id}", method: "delete", data: {confirm: "sure?"}, id: "document_#{document.id}" %>
此代码适用于modal:
<div id="modal-confirm" class="modal modal-confirm">
<h2 class="modal__ttl">Title</h2>
<div class="modal__inner">
<p>Description</p>
<div class="modal__btns">
<button type="button" name="cancel" id="cancel-delete" class="btn btn-primary">Cancel</button>
<button type="button" name="confirm" id="confirm-delete" class="btn delete_button btn-secondary">Delete</button>
</div>
</div>
</div>
标题
描述
取消
删除
我希望,它能帮助某些人。确认的全部目的是向用户询问一个带有“是”的问题/n