限制与 draggables 和 droppable 相关联的 sortable 中的元素数量

limit number of elements in a sortable connected with draggables and a droppable

我有一个可排序的、连接的可拖动对象和一个可放置对象。 它基本上是一个桶和一个可排序的项目列表。 我想限制您可以从存储桶拖到列表中的项目数。

我的问题是,如果列表中的项目数太多,我就无法恢复可拖动。我还从列表中删除了该项目,因此它也不会卡在那里。 但这是我的问题。 sortable 的更新事件最后触发。因此,当更新事件触发时,元素已被删除,因此项目数量少于允许的数量。我不想要这个,因为我在更新事件中更新了我的数据库。

我知道这个问题之前已经回答过,但请先阅读整个问题。

这里是 html:

<fieldset id="container">
<div style="float: left; width: 49%;">
    <fieldset class="choosen" style="float: left; width: 100%;">
        <legend>choosen</legend>
        <div style="overflow-y: auto; height: 40em;" class="box">
            <ul style="min-height: 40em;" class="imglist grey sortable">
                <li data-id="1" class="acceptable">Element1</li>
                <li data-id="2" class="acceptable">Element2</li>
                <li data-id="3" class="acceptable">Element3</li>
            </ul>
        </div>
    </fieldset>
</div>
<div style="float: left; margin-left: 2%; width: 49%;">
    <fieldset class="bucket" style="float: left; width: 100%;">
        <legend>bucket</legend>
        <div style="overflow-y: auto; height: 40em;" class="box droppable">
            <ul style="min-height: 40em;" class="imglist grey">
                <li data-id="5" class="draggable"><a>Element5</a>

                </li>
                <li data-id="6" class="draggable"><a>Element6</a>

                </li>
                <li data-id="7" class="draggable"><a>Element7</a>

                </li>
                <li data-id="8" class="draggable"><a>Element8</a>

                </li>
            </ul>
        </div>
    </fieldset>
</div>

这里是 jquery 代码:

var helperClone = function (event, object) {
    if (undefined == object) {
        var helper = $(this).clone(),
            height = $(this).height(),
            width = $(this).width();
    } else {
        var helper = object.clone(),
            height = object.height(),
            width = object.width();
    }
    helper.css({'width': width, 'height': height});
    return helper;
},
sortable = $(".sortable"),
draggable = $(".draggable"),
revertCheck = function () {
    console.log("revertCheck", sortable.find("li").length > 4, sortable.find("li").length);
    if (sortable.find("li").length > 4) {
        return true;
    }
    return false;
};
draggable.draggable({
    connectToSortable: sortable,
    helper: helperClone,
    revert: revertCheck
});
sortable.sortable({
    placeholder: "ui-state-highlight",
    helper: helperClone,
    receive: function (event, ui) {
        console.log("receive", $(this).find("li").length < 4,     $(this).find("li").length);
        if ($(this).find("li").length < 4) {
            ui.item.remove();
            $(this).data().uiSortable.currentItem.addClass('acceptable').css({
            'width': '100%',
                'height': 'unset'
        });
    } else {
        ui.helper.remove();
    }
},
update: function (event, ui) {
    console.log("update", $(this).find("li").length < 4, $(this).find("li").length);
    if ($(this).find("li").length < 4) {
        //do stuff
        console.log("update fired");
    } else {
        console.log("update didn't fire");
        ui.item.effect('highlight', {
            color: 'red'
        });
        }
    }
});

$(".droppable").droppable({
    accept: 'li.acceptable',
    over: function (event, ui) {
        $(this).effect('highlight');
    },
    drop: function (event, ui) {
        var target = $(this).find('ul');
        var clone = ui.draggable.clone().css({
            'display': 'list-item',
                'position': 'unset'
        });
        ui.draggable.remove();
        clone.appendTo(target).show().removeClass('acceptable').draggable({
            connectToSortable: sortable,
            containment: "#container",
            helper: helperClone,
            revert: revertCheck
        });
    }
});
$("ul, li").disableSelection();

这是一个工作示例:http://jsfiddle.net/adq6exkp/

其他答案建议在可排序的接收事件中调用sortable.sortable("cancel");。所以在上面的代码中,您可以将其添加到接收事件函数的 else 部分:

$(ui.sender).sortable('cancel');

问题是这引发了以下错误:

Error: cannot call methods on sortable prior to initialization; attempted to call method 'cancel' http://code.jquery.com/jquery-1.10.1.js Line 516

这里是这个错误的工作示例:http://jsfiddle.net/adq6exkp/1/

据我了解,您不希望在发生还原时触发更新。

您可以使用布尔值完成此操作。

sortable.sortable({
    placeholder: "ui-state-highlight",
    helper: helperClone,
    receive: function (event, ui) {
        console.log("receive", $(this).find("li").length < 4, $(this).find("li").length);
        if ($(this).find("li").length < 4) {
            ui.item.remove();
            $(this).data().uiSortable.currentItem.addClass('acceptable').css({
                'width': '100%',
                    'height': 'unset'
            });
        } else {
            this.reverted = true;
            ui.helper.remove();
        }
    },
    update: function (event, ui) {
        console.log("update", $(this).find("li").length < 4, $(this).find("li").length);
        if (!this.reverted) {
            //do stuff
            console.log("update fired");
        } else {
            this.reverted = false;
            console.log("update didn't fire");
            ui.item.effect('highlight', {
                color: 'red'
            });
        }
    }
});

Fiddle

您可以在 update 事件中处理 helper 删除。这样,列表中的元素数量在 receiveupdate 上都是一致的。但是由于你没有权限访问update事件中的helper,所以你需要先存储它。这可以在 receive 事件上完成。这样:

receive: function (event, ui) {
        //store current helper
        cur_helper = ui.helper;
        console.log("receive", $(this).find("li").length < 4, $(this).find("li").length);
        if ($(this).find("li").length < 4) {
            ui.item.remove();
            $(this).data().uiSortable.currentItem.addClass('acceptable').css({
                'width': '100%',
                    'height': 'unset'
            });
        } 
    },
    update: function (event, ui) {
        console.log("update", $(this).find("li").length < 4, $(this).find("li").length);
        if ($(this).find("li").length < 4) {
            //do stuff
            console.log("update fired");
        } else {
            //remove the helper if the list exceeds 3 
            cur_helper.remove();
            console.log("update didn't fire");
            ui.item.effect('highlight', {
                color: 'red'
            });
        }
    }

fiddle: http://jsfiddle.net/p0nft4mj/