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 ответ:
Итак, я упоминал, что ненавижу 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/