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

发布于 2024-12-08 00:23:37 字数 8461 浏览 0 评论 0原文

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

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

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

screenshot

前 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:

screenshot

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.

enter image description here

<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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦行七里 2024-12-15 00:23:37

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

更新:清理了解决方案,将复选框本身的初始状态存储在 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');
}

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.

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

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

And this is what your select/deselect should look like to only act on the open dialog:

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

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

And here is openDialog edited to use this instead of the jQuery selector:

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');
}
破晓 2024-12-15 00:23:37
  1. 在您的保存函数中,您应该调用服务器端脚本(使用 AJAX - 检查 jQuery 文档此处)并保存每个复选框的状态(当然,如果这是您愿意做的)
  2. 在取消功能中,我只是坚持关闭对话框,因为您不需要更改任何内容。回滚保存所做的更改是没有意义的,因为您始终可以选中/取消选中所需的复选框并再次保存它们。
  3. 如何仅处理当前打开对话框的复选框 - 为 div 容器分配唯一的 id 并使用 $('#div_id input[type="checkbox"]') 选择器
  1. In your save function you should call your server side script (using AJAX - check jQuery docs here) and save the state of each checkbox (if this is what you're willing to do of course)
  2. In cancel function I'd just stick with closing the dialog, since you don't need to change anything. Rolling back the changes made by save is pointless since you can always check / unckech desired checkboxes and save them again.
  3. How to only process the checkboxes of the currently open dialog only - assign a unique id to the div container and use $('#div_id input[type="checkbox"]') selector
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文