在 jQuery UI 对话框中显示复选框并提供取消按钮

Posted

技术标签:

【中文标题】在 jQuery UI 对话框中显示复选框并提供取消按钮【英文标题】:Display checkboxes in jQuery UI dialogs and provide Cancel button 【发布时间】:2011-11-30 16:07:08 【问题描述】:

我正在尝试解决一个可能很常见的问题,并准备了一个简化的测试用例来展示它和我的努力。

我正在尝试显示几个 jQuery UI 对话框,每个对话框都包含多个同名复选框(在下面的测试代码中,fruitscandy

在每个对话框中我有 4 个按钮:保存取消全选取消全选

前 3 个按钮已经在我的代码中工作了。

更新按钮实际上是call DataTable's fnDraw() function,这部分也已经在工作了。 (而且我不想将复选框值保存在服务器上,我想在客户端做所有事情 - 我知道,这是可能的)。

我的问题是为对话框实现 Cancel 按钮:

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>

UPDATE2:实际上我有第三个和更大的问题:对话框右上角的关闭 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).dialog('close')

我没有看到一个简单的方法来解决它:如果我创建一个单独的函数

function restore() 
        $(this).find(':checkbox').each(function() 
            $(this).prop('checked', $(this).data('XXX'));
        );


function cancel() 
        restore();
        $(this).dialog('close');

并将其作为 close: restore 传递给对话框,然后 Save 按钮中断

【问题讨论】:

【参考方案1】:

我对您的代码进行了一些修改。可能最简单的事情(不一定是最好的)是将状态保存在全局变量中。 (更强大的解决方案可能只涉及将状态与对话框状态/选项一起保存)。

更新:清理了将复选框本身的初始状态存储在 DOM 中而不是全局变量中的解决方案。

http://jsfiddle.net/rhdNH/8/

我添加了一个自定义打开功能,方便保存状态,并完成了取消功能。您可能还想在使用removeProp 关闭时清理“原始”属性,但这不是绝对必要的。

以下是您将对第 1 点 (open:openDialog) 进行的更改,以便不必直接调用 openDialog。

$('#fruits').dialog( 
    autoOpen: false, 
    modal: true,
    buttons: buttons,
    open: openDialog
);

$('#candy').dialog( 
    autoOpen: false, 
    modal: true,
    buttons: buttons,
    open: openDialog
);

这就是你的选择/取消选择应该只对打开的对话框起作用:

function select() 
    $(':checkbox', this).prop('checked', true);


function deselect() 
    $(':checkbox', this).prop('checked', false);

这里将openDialog 编辑为使用this 而不是jQuery 选择器:

function openDialog() 
    $(':checkbox', this).each(function() 
        $(this).prop('original', $(this).is(':checked'));
    );


function cancel() 
        $(this).find('input[type="checkbox"]').each(function() 
            $(this).prop('checked', $(this).prop('original'));
        );
        $(this).dialog('close');

【讨论】:

谢谢。所以你在复选框本身中将复选框状态保存为 original="true" ?为什么是“原创”,是任意的名字吗? 只是另一个注意事项,您可以使用.data 而不是.prop 以更标准:***.com/questions/432174/… -- 虽然在任意属性中存储简单布尔值,但您不应该遇到内存泄漏要么。 谢谢你,有你的帮助我快到了,但请看看我更新的问题。 第二点:$(':checkbox', this).prop('checked', true);。我再看看另一个。 是的。更新了我的答案。您可以通过移除 x 按钮来处理它。 ***.com/questions/896777/…【参考方案2】:
    在您的保存功能中,您应该调用服务器端脚本(使用 AJAX - 检查 jQuery 文档here)并保存每个复选框的状态(当然,如果您愿意这样做) 在取消功能中,我只是坚持关闭对话框,因为您不需要更改任何内容。回滚保存所做的更改是没有意义的,因为您始终可以选中/取消选中所需的复选框并再次保存它们。 如何仅处理当前打开的对话框的复选框 - 为 div 容器分配唯一的 id 并使用 $('#div_id input[type="checkbox"]') 选择器

【讨论】:

抱歉,您的建议 1. 和 2. 不适合我 - 因为我不想通过服务器。我想在客户端使用(并保存)复选框信息,这已经有效 - 请参阅我当前问题中的 DataTables 问题链接。

以上是关于在 jQuery UI 对话框中显示复选框并提供取消按钮的主要内容,如果未能解决你的问题,请参考以下文章

jQuery-UI 自动完成不会显示在 jQuery-UI 对话框中

如何在显示效果期间制作 jQuery UI 对话框模式?

打开带有动态内容的 jQuery UI 对话框

TinyMCE 编辑器未在 JQuery UI 对话框中显示

jQuery-ui 对话框不显示在点击事件上

jQuery ui 关闭按钮未显示,但可以正常工作