jQuery Sortable-позволяет отбрасывать некоторые элементы только в определенные списки


Я использую jQuery UI Sortable для реализации категоризированного выбора, связанного с набором переключателей. Эта часть хорошо работает уже пару лет. (см.версию jsFiddle.Теперь клиент хочет изменить его: некоторые элементы теперь должны быть разрешены только в определенные категории, и я полностью застрял.

На задней стороне вещей достаточно легко отключить некоторые переключатели:

<ul id="L" class="L ui-sortable">
    Available (A):
    <li id='L_1'>
    <input type='radio' name='L_1' id='L_1_A' value='A'>
      <label for='L_1_A'>A</label>
    <input type='radio' name='L_1' id='L_1_B' disabled='disabled' value='B'>
      <label for='L_1_B'>B</label>
    <input type='radio' name='L_1' id='L_1_C' value='C'>
      <label for='L_1_C'>C</label>
    Item 1 can't go in B
    </li>
    <li id='L_2'>
    <input type='radio' name='L_2' id='L_2_A' value='A'>
      <label for='L_2_A'>A</label>
    <input type='radio' name='L_2' id='L_2_B' value='B'>
      <label for='L_2_B'>B</label>
    <input type='radio' name='L_2' id='L_2_C' disabled='disabled' value='C'>
      <label for='L_2_C'>C</label>
    Item 2 can't go in C
    </li>
    <!-- etc. -->
</ul>
<ul id='L_B' class='L ui-sortable cat'>Selected - B</ul>
<ul id='L_C' class='L ui-sortable cat'>Selected - C</ul>

(переключатели скрыты с помощью комбинации CSS и Яваскрипт.) Это имеет побочный эффект, делающий невозможным сохранение неправильных классификаций: если вы пытаетесь поместить что-то в категорию, в которую оно не может войти, ваш выбор полностью игнорируется (потому что отключенный переключатель не возвращает значение). Однако, если вы не вернетесь и не посмотрите на сохраненную запись, вы никогда не узнаете, что произошло: вам кажется, что вы положили предмет в коробку, как обычно.

То, что я хотел бы для коробки назначения, которая связана с отключенным радио кнопка "посереет", когда предмет будет схвачен, и если они все еще пытаются положить его в эту коробку, предмет должен вернуться к своей начальной точке. В принципе, он должен вести себя так, как если бы вы установили $("ul.notallowed").sortable("option","disabled",true);, но только в то время, когда пользователь "держит" запрещенный элемент.

Я знаю, что есть команда .is(":disabled"), чтобы выяснить, отключен ли переключатель, но я понятия не имею, куда его поместить.

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

$(function() {
    $("#L").sortable({
        connectWith: '.L',
        containment: '#ListContainer',
        receive: function(event, ui) {
            $(ui.item).find('input:radio')[0].checked = true;
        }
    }).disableSelection();
    $("#L_B").sortable({
        connectWith: '.L',
        containment: '#ListContainer',
        receive: function(event, ui) {
            $(ui.item).find('input:radio')[1].checked = true;
        }
    }).disableSelection();
    $("#L_C").sortable({
        connectWith: '.L',
        containment: '#ListContainer',
        receive: function(event, ui) {
            $(ui.item).find('input:radio')[2].checked = true;
        }
    }).disableSelection();
});
$(document).ready(function() {
    $('.B').closest('li').appendTo("#L_B");
    $('.C').closest('li').appendTo("#L_C");
    $('ul.ui-sortable').width("10em");
    $('ul.ui-sortable li').css({cursor:'pointer'});
});

Я должен отметить, что я полностью отстой в языках программирования, которые включают фигурные скобки. Я написал вышеописанный код, но я не могу сказать вам, что делает большая его часть, не говоря уже о том, почему он работает. Поэтому, если бы вы могли сформулировать свои ответы в самых простых терминах, я был бы очень признателен.

1 2

1 ответ:

Итак, я упоминал, что ненавижу JavaScript? Но у меня получилось (без седины, но я давно перестал заботиться об этом) с сединой и всем остальным.

Часть 1, Забудьте об обнаружении отключенных переключателей в jQuery. ((":disabled") работает как селектор, но возвращает переключатель, а не его родительский элемент списка.) Вместо этого просто добавьте класс (или классы) к элементам списка.

<li class="noB">
    <label><input type="radio" name="L1" value="A" />A</label>
    <label><input type="radio" name="L1" value="B" disabled="disabled" />B</label>
    <label><input type="radio" name="L1" value="C" />C</label>
    Item 1 can't go in B
</li>

Часть 2, в функциях "receive" списков назначения, условно отмените сортировку для объекта jQuerysender . Например,

$("#L_B").sortable({
    connectWith: '.L',
    containment: '#ListContainer',
    receive: function (event, ui) {
        if ($(ui.item).hasClass("noB")) {
            $(ui.sender).sortable("cancel");
        }
        else {
            $(ui.item).find('input:radio')[1].checked = true;
        }
    },
}).disableSelection();

The .отправитель имеет решающее значение: я не знаю, сколько волос я навсегда потерял, пробуя различные вещи с ui.item или li.noB или что-то еще. (Это имеет мало смысла для меня: то, что я хочу предотвратить, это поместить элемент в неправильном месте, так почему мне нужно отменитьудаление из родительского списка? Но все равно.)

Часть 3 в моем случае заключалась в перемещении списка метки из списков, потому что, кроме того, что они не совсем корректны, они заставляют cancel делать вещи straaaange.

Часть 4, серость: используйте .addClass в функции "старт" и .removeClass в функции "стоп" каждой сортируемой коробки. Я ставлю их после receive: function(...) {...}, но порядок не должен иметь значения. (Несомненно, есть какой-то способ написать эту функцию один раз и вызывать ее каждый раз, но я уже упоминал, что JavaScript и я не ладим?)

    start: function (event, ui) {
        if ($(ui.item).hasClass("noB")) {
            $("#L_B").addClass("disabled");
        }
        if ($(ui.item).hasClass("noC")) {
            $("#L_C").addClass("disabled");
        }
    },
    stop: function (event, ui) {
        if ($(ui.item).hasClass("noB")) {
            $("#L_B").removeClass("disabled");
        }
        if ($(ui.item).hasClass("noC")) {
            $("#L_C").removeClass("disabled");
        }
    }

Не забудьте определить класс" disabled " в вашем CSS, иначе все эти гимнастические упражнения будут делать именно так... ничего.

Рабочий jsFiddle: http://jsfiddle.net/NY7Ms/4/