目前,我正在努力用jquery对话框替换“alert”/“confirm”。
但是大多数遗留代码是以某种异步方式编写的,这使得它很难改变。有没有办法让jquery对话框以同步方式工作? (不要使用循环或回调函数)
For example:
function run()
{
var result = confirm("yes or no");
alert( result );
\\more codes here
}
在此示例中,警报和其他代码将在用户选择后执行。
如果我们使用jquery对话框 var result = $ dialog.open() 它将继续执行异步警报。
目前,我的解决方案是在OK | Cancel功能中使用回调函数。 例如:
OK: function ()
{
$dialog.close();
alert("yes");
//more codes here
}
此方法有效,但很难使所有同步代码变为异步,这需要进行大量更改(请参阅下面的示例)。 所以我正在寻找同步jQuery对话框,有可能吗?
例如:(实际代码比下面的例子复杂得多)
function f1()
{
if ( confirm("hello") ) f2();
alert("no");
}
function f2()
{
if( confirm("world") ) f3();
alert("no");
}
function f3()
{
return confirm("!") ;
}
另一个例子:
vendorObject.on('some-event', function() {
if(confirm("Do you really want to do that?")) {
return true;
}
else {
return false; // cancel the event
}
});
...此处供应商对象触发一个事件,如果用户确认,该事件必须被取消。只有事件处理程序同步返回false
时才能取消该事件。
答案 0 :(得分:35)
简短的回答是否定的,您将无法保持代码同步。原因如下:
为说明此行为,请调试代码并在更改UI的行后面的行上设置断点:
$("body").css("backgroundColor", "red");
var x = 1; // break on this line
请注意,您的网页背景还不是红色。在您恢复执行并且脚本完成执行之前,它不会更改为红色。当您的调试器暂停执行脚本时,您也无法单击页面中的任何链接。
alert()
和confirm()
此规则有例外。这些是浏览器控件,其处理方式与实际网页UI元素不同。
好消息是转换代码真的不是很难。据推测,您的代码目前看起来像这样:
if (confirm("continue?")) {
// several lines of code if yes
}
else {
// several lines of code if no
}
// several lines of code finally
你的异步版本可以创建一个函数ifConfirm(text, yesFn, noFn, finallyFn)
,你的代码看起来非常相似:
ifConfirm("continue?", function () {
// several lines of code if yes
},
function () {
// several lines of code if no
},
function () {
// several lines of code finally
});
修改:为了回应您添加到问题中的其他示例,遗憾的是,该代码需要重构。只有不可能才能拥有同步自定义确认对话框。要在事件需要继续或取消的场景中使用自定义确认对话框,您只需要始终取消事件并模仿yesFn
回调中的事件。
例如,链接:
$("a[href]").click(function (e) {
e.preventDefault();
var link = this.href;
ifConfirm("Are you sure you want to leave this awesome page?", function () {
location.href = link;
});
});
或者,表格:
$("form").submit(function (e) {
e.preventDefault();
var form = this;
ifConfirm("Are you sure you're ready to submit this form?", function () {
form.submit();
});
});
答案 1 :(得分:8)
我不确定不使用回调的动机是什么,因此很难判断哪种解决方案可能满足您的要求,但延迟执行的另一种方法是通过jQuery的“延迟”对象。
http://api.jquery.com/category/deferred-object/
您可以设置一个打开jquery对话框的函数,并添加“等待”对话框关闭的代码。在你已经布局的情况下,这最终会以与回调相似的方式工作,但这是一个例子:
function confirm () {
var defer = $.Deferred();
$('<div>Do you want to continue?</div>').dialog({
autoOpen: true,
close: function () {
$(this).dialog('destroy');
},
position: ['left', 'top'],
title: 'Continue?',
buttons: {
"Yes": function() {
defer.resolve("yes"); //on Yes click, end deferred state successfully with yes value
$( this ).dialog( "close" );
},
"No": function() {
defer.resolve("no"); //on No click end deferred successfully with no value
$( this ).dialog( "close" );
}
}
});
return defer.promise(); //important to return the deferred promise
}
$(document).ready(function () {
$('#prod_btn').click(function () {
confirm().then(function (answer) {//then will run if Yes or No is clicked
alert('run all my code on ' + answer);
});
});
});
这里有jsFiddle:http://jsfiddle.net/FJMuJ/
答案 2 :(得分:3)
不,你不能在Javascript中做任何同步(警报实际上违反了规则)。 Javascript是在核心中使用“单线程,异步”构建的。
但是,您可以执行的操作是禁用基础页面的功能(类似灯箱),因此在您不执行对话操作之前,不会从页面触发任何事件,无论是OK还是取消。认为这无助于您使同步代码正常工作。你必须改写。
答案 3 :(得分:1)
答案 4 :(得分:0)
回答大卫怀特曼更具体的问题,这里是我如何实施一个延迟的&#34; LinkButton Click事件的回发。基本上,我只是防止默认行为并在用户反馈可用时手动触发回发。
function MyClientClickHandler(event, confirmationMessage, yesText, noText) {
// My LinkButtons are created dynamically, so I compute the caller's ID
var elementName = event.srcElement.id.replace(/_/g, '$');
// I don't want the event to be fired immediately because I want to add a parameter based on user's input
event.preventDefault();
$('<p>' + confirmationMessage + '</p>').dialog({
buttons: [
{
text: yesText,
click: function () {
$(this).dialog("close");
// Now I'm ready to fire the postback
__doPostBack(elementName, 'Y');
}
},
{
text: noText,
click: function () {
$(this).dialog("close");
// In my case, I need a postback when the user presses "no" as well
__doPostBack(elementName, 'N');
}
}
]
});
}
答案 5 :(得分:0)
您可以使用真实的模态对话框。
[对话框]是网页中弹出框的元素,包括模式选项,该选项将使页面的其余部分在使用过程中保持惰性。在阻止用户交互直到用户给您答复或确认操作之前,这可能很有用。
答案 6 :(得分:-1)
我真的不明白为什么你反对使用Jquery回调来实现你的例子中的行为。你肯定要重写一些代码,但是:
function f1() {
$( "#testdiv" ).dialog({
modal: true,
buttons: {
"OK": function() {
$( this ).dialog( "close" );
f2();
},
Cancel: function() {
$( this ).dialog( "close" );
alert('no');
}
}
});
}
function f2() {
$( "#testdiv2" ).dialog({
modal: true,
buttons: {
"OK": function() {
$( this ).dialog( "close" );
f3();
},
Cancel: function() {
$( this ).dialog( "close" );
alert('no');
}
}
});
}
function f3() {
$( "#testdiv3" ).dialog({
modal: true,
buttons: {
"OK": function() {
$( this ).dialog( "close" );
},
Cancel: function() {
$( this ).dialog( "close" );
}
}
});
}
<div id="testdiv" title="Hello"/>
<div id="testdiv2" title="World"/>
<div id="testdiv3" title="!"/>