在 jQuery UI 对话框中显示复选框并提供取消按钮
我正在尝试解决可能是一个非常常见的问题,并准备了一个简化的测试用例来展示它和我的努力。
我正在尝试显示几个 jQuery UI 对话框,每个对话框都包含多个同名的复选框(下面的测试代码中的 fruits 和 candy)
在每个对话框中我有 4 个按钮:保存、取消、全选和取消全选:
前 3 个按钮已在我的代码中工作。
更新按钮实际上会调用DataTable的fnDraw () 函数,该部分也已经可以工作了。 (我不想在服务器上保存复选框值,我想在客户端做所有事情 - 我知道,这是可能的)。
我的问题是实现对话框的取消按钮:
1)我应该在对话框打开事件上保存当前设置的复选框列表?然后点击取消即可恢复它们?有一些优雅的 jQuery 方法吗?
2)我不知道如何仅处理当前打开的对话框的复选框。
下面是我当前的测试代码,它可以立即运行 - 感谢 Google CDN:
<html>
<head>
<style type="text/css" title="currentStyle">
@import "http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.0/themes/redmond/jquery-ui.css";
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script type="text/javascript">
$(function() {
var buttons = {
Cancel: cancel,
Save: save,
'Deselect All': deselect,
'Select All': select
};
$('#fruits').dialog({
autoOpen: false,
modal: true,
buttons: buttons
});
$('#candy').dialog({
autoOpen: false,
modal: true,
buttons: buttons
});
});
function update() {
var boxes = new Array();
$(':checkbox').each(function() {
if ($(this).is(':checked')) {
boxes.push(
$(this).attr('name') +
'=' +
$(this).val()
);
}
});
alert('boxes: ' + boxes.join('&'));
}
function select() {
$(':checkbox').prop('checked', true);
}
function deselect() {
$(':checkbox').prop('checked', false);
}
function save() {
// XXX how to implement?
$(this).dialog('close');
}
function cancel() {
// XXX how to implement?
$(this).dialog('close');
}
</script>
</head>
<body>
<p><input type="button" value="Select fruits" onclick="$('#fruits').dialog('open');"></p>
<div id="fruits" title="fruits">
<p><label><input type="checkbox" name="fruits" value="apple">apple</label></p>
<p><label><input type="checkbox" name="fruits" value="banana">banana</label></p>
<p><label><input type="checkbox" name="fruits" value="pear">pear</label></p>
</div>
<p><input type="button" value="Select candy" onclick="$('#candy').dialog('open');"></p>
<div id="candy" title="candy">
<p><label><input type="checkbox" name="candy" value="toffee">toffee</label></p>
<p><label><input type="checkbox" name="candy" value="fudge">fudge</label></p>
</div>
<p><input type="button" onclick="update();" value="Update"></p>
</body>
</html>
更新: 感谢 mootinator,以下代码可以运行,但我仍然有 2 个小问题/疑问:
1)是否可以使用 open 事件而不是自定义 openDialog() 方法?
2) 我的取消全选和全选按钮修改页面上的所有复选框 - 而不是仅修改属于当前对话框的复选框。我想知道如何只选择后者? (以某种方式在 selectAll() 和 deselectAll() 中使用 $(this) )?
我已经尝试过
function selectAll() {
$($(this) + ' :checkbox').prop('checked', true);
}
function deselectAll() {
$($(this) + ' :checkbox').prop('checked', false);
}
,但出现语法错误。
<html>
<head>
<style type="text/css" title="currentStyle">
@import "/css/demo_table_jui.css";
@import "http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.0/themes/redmond/jquery-ui.css";
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script type="text/javascript" src="/js/jquery.dataTables.min.js"></script>
<script type="text/javascript">
$(function() {
var buttons = {
Cancel: cancel,
Save: save,
'Deselect All': deselectAll,
'Select All': selectAll
};
$('#openCandy').button();
$('#openFruits').button();
$('#update').button();
$('#openCandy').click(function() {
openDialog('#candy');
});
$('#openFruits').click(function() {
openDialog('#fruits');
});
$('#fruits').dialog({
autoOpen: false,
modal: true,
buttons: buttons
});
$('#candy').dialog({
autoOpen: false,
modal: true,
buttons: buttons
});
});
function update() {
var boxes = new Array();
$(':checkbox').each(function() {
if ($(this).is(':checked')) {
boxes.push(
$(this).attr('name') +
'=' +
$(this).val()
);
}
});
alert('boxes: ' + boxes.join('&'));
}
function selectAll() {
$(':checkbox').prop('checked', true);
}
function deselectAll() {
$(':checkbox').prop('checked', false);
}
function openDialog(sel) {
$(sel).dialog('open');
$(sel + ' :checkbox').each(function() {
$(this).data('XXX', $(this).is(':checked'));
});
}
function cancel() {
$(this).find(':checkbox').each(function() {
$(this).prop('checked', $(this).data('XXX'));
});
$(this).dialog('close');
}
function save() {
$(this).dialog('close');
}
</script>
</head>
<body>
<p><input id="openFruits" type="button" value="Select fruits"></p>
<div id="fruits" title="fruits">
<p><label><input type="checkbox" name="fruits" value="apple">apple</label></p>
<p><label><input type="checkbox" name="fruits" value="banana">banana</label></p>
<p><label><input type="checkbox" name="fruits" value="pear">pear</label></p>
</div>
<p><input id="openCandy" type="button" value="Select candy"></p>
<div id="candy" title="candy">
<p><label><input type="checkbox" name="candy" value="toffee">toffee</label></p>
<p><label><input type="checkbox" name="candy" value="fudge">fudge</label></p>
</div>
<p><input id="update" type="button" onclick="update();" value="Update"></p>
</body>
</html>
更新2:实际上我有一个第三个更大的问题:关闭X-对话框右上角的按钮无法正常工作(它保存而不是取消)。
我尝试在两个对话框中添加 close: cancel, ,但在 Chrome 中出现运行时错误:
Uncaught RangeError: Maximum call stack size exceeded
f.event.remove
f.event.remove
f.fn.extend.unbind
a.extend.destroy
a.extend.destroy
a.widget.close
a.widget.bridge.a.fn.(anonymous function)
e.extend.each
e.fn.e.each
a.widget.bridge.a.fn.(anonymous function)
cancel
a.Widget._trigger
a.widget.close
a.widget.bridge.a.fn.(anonymous function)
.....etc....
UPDATE3: 可能是因为我调用了 $(this).循环中的对话框('close')?
不过,我没有找到解决此问题的简单方法:如果我创建一个单独的函数
function restore() {
$(this).find(':checkbox').each(function() {
$(this).prop('checked', $(this).data('XXX'));
});
}
function cancel() {
restore();
$(this).dialog('close');
}
并将其作为 close:restore 传递给对话框,则 保存 按钮会损坏
I'm trying to solve probably a very common problem and have prepared a simplified test case demonstrating it and my efforts.
I'm trying to display several jQuery UI dialogs, each containing several checkboxes of the same name (fruits and candy in my test code below)
In each dialog I have 4 buttons: Save, Cancel, Select all and Deselect all:
The first 3 buttons are already working in my code.
The Update button will in fact call DataTable's fnDraw() function, that part is already working too. (And I don't want to save the checkboxes values on the server inbetween, I'd like to do everything on the client-side - I know, this is possible).
My problem is in implementing the Cancel button for the dialogs:
1) I should probably save a list of currently set checkboxes on the dialog open event? And then restore them on Cancel click? Is there some elegant jQuery-way for that?
2) I don't know, how to only process the checkboxes of the currently open dialog only.
Below is my current test code, it works instantly - thanks to Google CDN:
<html>
<head>
<style type="text/css" title="currentStyle">
@import "http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.0/themes/redmond/jquery-ui.css";
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script type="text/javascript">
$(function() {
var buttons = {
Cancel: cancel,
Save: save,
'Deselect All': deselect,
'Select All': select
};
$('#fruits').dialog({
autoOpen: false,
modal: true,
buttons: buttons
});
$('#candy').dialog({
autoOpen: false,
modal: true,
buttons: buttons
});
});
function update() {
var boxes = new Array();
$(':checkbox').each(function() {
if ($(this).is(':checked')) {
boxes.push(
$(this).attr('name') +
'=' +
$(this).val()
);
}
});
alert('boxes: ' + boxes.join('&'));
}
function select() {
$(':checkbox').prop('checked', true);
}
function deselect() {
$(':checkbox').prop('checked', false);
}
function save() {
// XXX how to implement?
$(this).dialog('close');
}
function cancel() {
// XXX how to implement?
$(this).dialog('close');
}
</script>
</head>
<body>
<p><input type="button" value="Select fruits" onclick="$('#fruits').dialog('open');"></p>
<div id="fruits" title="fruits">
<p><label><input type="checkbox" name="fruits" value="apple">apple</label></p>
<p><label><input type="checkbox" name="fruits" value="banana">banana</label></p>
<p><label><input type="checkbox" name="fruits" value="pear">pear</label></p>
</div>
<p><input type="button" value="Select candy" onclick="$('#candy').dialog('open');"></p>
<div id="candy" title="candy">
<p><label><input type="checkbox" name="candy" value="toffee">toffee</label></p>
<p><label><input type="checkbox" name="candy" value="fudge">fudge</label></p>
</div>
<p><input type="button" onclick="update();" value="Update"></p>
</body>
</html>
UPDATE: Thanks to mootinator the following code is working, but I still have 2 minor issues/questions:
1) Is it possible to use open event instead of the custom openDialog()method?
2) My Deselect All and Select All buttons modify all checkboxes at the page - instead of modifying only those belonging to the current dialog. I wonder how to select only the latter ones? (somehow use $(this) in selectAll() and deselectAll())?
I've tried
function selectAll() {
$($(this) + ' :checkbox').prop('checked', true);
}
function deselectAll() {
$($(this) + ' :checkbox').prop('checked', false);
}
but get syntax error.
<html>
<head>
<style type="text/css" title="currentStyle">
@import "/css/demo_table_jui.css";
@import "http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.0/themes/redmond/jquery-ui.css";
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script type="text/javascript" src="/js/jquery.dataTables.min.js"></script>
<script type="text/javascript">
$(function() {
var buttons = {
Cancel: cancel,
Save: save,
'Deselect All': deselectAll,
'Select All': selectAll
};
$('#openCandy').button();
$('#openFruits').button();
$('#update').button();
$('#openCandy').click(function() {
openDialog('#candy');
});
$('#openFruits').click(function() {
openDialog('#fruits');
});
$('#fruits').dialog({
autoOpen: false,
modal: true,
buttons: buttons
});
$('#candy').dialog({
autoOpen: false,
modal: true,
buttons: buttons
});
});
function update() {
var boxes = new Array();
$(':checkbox').each(function() {
if ($(this).is(':checked')) {
boxes.push(
$(this).attr('name') +
'=' +
$(this).val()
);
}
});
alert('boxes: ' + boxes.join('&'));
}
function selectAll() {
$(':checkbox').prop('checked', true);
}
function deselectAll() {
$(':checkbox').prop('checked', false);
}
function openDialog(sel) {
$(sel).dialog('open');
$(sel + ' :checkbox').each(function() {
$(this).data('XXX', $(this).is(':checked'));
});
}
function cancel() {
$(this).find(':checkbox').each(function() {
$(this).prop('checked', $(this).data('XXX'));
});
$(this).dialog('close');
}
function save() {
$(this).dialog('close');
}
</script>
</head>
<body>
<p><input id="openFruits" type="button" value="Select fruits"></p>
<div id="fruits" title="fruits">
<p><label><input type="checkbox" name="fruits" value="apple">apple</label></p>
<p><label><input type="checkbox" name="fruits" value="banana">banana</label></p>
<p><label><input type="checkbox" name="fruits" value="pear">pear</label></p>
</div>
<p><input id="openCandy" type="button" value="Select candy"></p>
<div id="candy" title="candy">
<p><label><input type="checkbox" name="candy" value="toffee">toffee</label></p>
<p><label><input type="checkbox" name="candy" value="fudge">fudge</label></p>
</div>
<p><input id="update" type="button" onclick="update();" value="Update"></p>
</body>
</html>
UPDATE2: Actually I have a 3rd and bigger problem: the closing X-button on the top-right corner of the dialog doesn't work as it should (it saves instead of cancelling).
I've tried adding close: cancel, to both dialogs, but I get the runtime error in Chrome:
Uncaught RangeError: Maximum call stack size exceeded
f.event.remove
f.event.remove
f.fn.extend.unbind
a.extend.destroy
a.extend.destroy
a.widget.close
a.widget.bridge.a.fn.(anonymous function)
e.extend.each
e.fn.e.each
a.widget.bridge.a.fn.(anonymous function)
cancel
a.Widget._trigger
a.widget.close
a.widget.bridge.a.fn.(anonymous function)
.....etc....
UPDATE3: Probably because I call $(this).dialog('close') in a loop?
I don't see an easy way to fix it though: if I create a separate function
function restore() {
$(this).find(':checkbox').each(function() {
$(this).prop('checked', $(this).data('XXX'));
});
}
function cancel() {
restore();
$(this).dialog('close');
}
and pass it as close: restore to dialogs, then the Save button breaks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我对您的代码做了一些修改。也许最简单的事情(不一定是最好的)是将状态保存在全局变量中。 (更强大的解决方案可能只涉及将状态与对话框状态/选项一起保存)。
更新:清理了解决方案,将复选框本身的初始状态存储在 DOM 中,而不是存储在全局变量中。
http://jsfiddle.net/rhdNH/8/
我添加了自定义打开功能,以方便保存状态,并完成取消功能。每当您使用
removeProp
关闭时,您可能还想清理“原始”属性,但这并不是绝对必要的。以下是您需要对第 1 点 (open:openDialog) 进行的更改,以便不必直接调用 openDialog。
这就是你的选择/取消选择应该看起来像只作用于打开的对话框:
这里是
openDialog
编辑为使用this
而不是 jQuery 选择器:I made a couple of modifications to your code. Probably the easiest thing to do (not necessarily the best) would be to save the state in a global variable. (A more robust solution might just involve saving the state alongside the dialog state/options).
UPDATE: Cleaned up the solution to store the initial state on the checkbox itself in the DOM instead of in a global variable.
http://jsfiddle.net/rhdNH/8/
I added a custom open function to facilitate saving the state, and completed the cancel function. You may want to also clean up the 'original' properties whenever you close using
removeProp
, but it isn't strictly necessary.Here are the changes you would make for point #1 (open:openDialog) in order to not have to call openDialog directly.
And this is what your select/deselect should look like to only act on the open dialog:
And here is
openDialog
edited to usethis
instead of the jQuery selector:$('#div_id input[type="checkbox"]')
选择器$('#div_id input[type="checkbox"]')
selector