jQuery可排序-允许某些项目仅被放置在特定列表中

3
我正在使用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和javascript的组合)隐藏了单选按钮。这样做的副作用是使保存不当分类成为不可能:如果您试图将某些东西放入它不能进入的类别中,则您的选择将被完全忽略(因为禁用的单选按钮不返回值)。但是,除非您回去查看已保存的记录,否则您永远不会知道发生了什么:对您来说,看起来像是按照惯例将项目放在盒子里。

我想要的是,与禁用的单选按钮相关联的目标框在抓取物品时“变灰”,如果他们仍然试图将其放入该框中,则该项应跳回其起始点。基本上,它应该表现得像设置$("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'});
});

我应该指出,我完全不擅长涉及花括号的编程语言。我写了上面的代码,但我几乎不知道它的大部分功能,更别提为什么它能工作了。所以如果你能用尽可能简单的术语来回答我的问题,我将不胜感激。


我在 Codecademy 的课程中做了类似的东西... 我将会发布代码和练习的链接。 - Hackerman
1个回答

9

所以,我提到过我讨厌JavaScript吗?但是我通过灰度调整等方法让它工作了(虽然没有灰掉,但我已经不再关心这个问题了)

第一部分,请忘记在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>

在目标列表的“接收”函数的Part 2中,有条件地取消发送方jQuery对象的可排序性。例如:

$("#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();

在这里,.sender 部分非常重要:我曾经试过各种方法来处理 ui.itemli.noB 等等,但却让我失去了很多头发。 (对我来说没有太多意义:我想要防止的是将项目放置在错误的位置,那么为什么我需要取消它从父列表中删除呢?但无论如何。)

在我的情况下,第三步是将列表标签移出列表,因为除了不太有效之外,它还会使 cancel 做一些奇怪的事情。

第四步,变灰:在每个可排序框的“开始”函数中使用 .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");
        }
    }

请不要忘记在你的CSS中定义“disabled”类,否则所有这些花样都会毫无作用。
工作的jsFiddle: http://jsfiddle.net/NY7Ms/4/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接