Отобразите флажки в диалоговых окнах jQuery UI и предоставьте кнопку Отмена - PullRequest
8 голосов
/ 04 октября 2011

Я пытаюсь решить, вероятно, очень распространенную проблему и подготовил упрощенный тестовый пример, демонстрирующий это и мои усилия.

Я пытаюсь отобразить несколько диалоговых окон jQuery UI, каждый из которых содержит несколько флажков с одинаковыми именами ( fruits и candy в моем тестовом коде ниже)

В каждом диалоге у меня есть 4 кнопки: Сохранить , Отмена , Выбрать все и Отменить выбор всех :

screenshot

Первые 3 кнопки уже работают в моем коде.

Кнопка Update на самом деле вызовет функцию 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) Кнопки «Отменить выбор всех» и «Выбрать все» изменяют все флажки на странице, а не только те, которые принадлежат текущему диалоговому окну. Интересно, как выбрать только последние? (каким-то образом используйте $ (this) в selectAll () и deselectAll ())?

Я пробовал

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

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

но получите синтаксическую ошибку.

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>

ОБНОВЛЕНИЕ 2: На самом деле у меня есть 3-я и более серьезная проблема: закрывающая 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: восстановить в диалогах, затем кнопка Save обрывает

Ответы [ 2 ]

1 голос
/ 09 октября 2011

Я сделал пару изменений в вашем коде. Вероятно, самый простой способ (не обязательно лучший) - сохранить состояние в глобальной переменной. (Более надежное решение может просто включать сохранение состояния вместе с состоянием / параметрами диалога).

ОБНОВЛЕНИЕ : Исправлено решение для сохранения начального состояния на самом флажке в 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');
}
0 голосов
/ 04 октября 2011
  1. В вашей функции сохранения вы должны вызвать свой серверный скрипт (используя AJAX - проверьте jQuery docs здесь ) и сохранить состояние каждого флажка (если это то, что вы, конечно, хотите делать)
  2. В функции отмены я бы просто закрыл диалоговое окно, так как вам не нужно ничего менять. Откат изменений, выполненных с помощью сохранения, не имеет смысла, так как вы всегда можете установить / снять флажки и сохранить их снова.
  3. Как обрабатывать только флажки только в текущем открытом диалоговом окне - назначьте уникальный идентификатор контейнеру div и используйте $('#div_id input[type="checkbox"]') селектор
...