限制与draggables和droppable连接的可排序元素的数量

时间:2015-05-20 09:53:43

标签: jquery jquery-ui jquery-ui-draggable jquery-ui-sortable jquery-ui-droppable

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

我的问题是,如果列表中的项目数量很高,我就可以恢复拖动。此外,我从列表中删除该项目,以便它也不会卡在那里。 但这是我的问题。可排序的更新事件最后发生。因此,当更新事件触发时,元素已被删除,因此项目数量少于允许数量。在更新事件中更新我的数据库时,我不希望这样。

我知道这个问题之前已经得到解答,但首先要阅读整个问题。

这是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");。因此,在上面的代码中,您可以将其添加到receive事件函数的else部分:

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

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

  

错误:在初始化之前无法调用sortable上的方法;试图调用方法'取消'   http://code.jquery.com/jquery-1.10.1.js   516行

以下是此错误的工作示例:http://jsfiddle.net/adq6exkp/1/

2 个答案:

答案 0 :(得分:2)

您可以在helper事件中处理update删除。这样,列表中的元素数量在receiveupdate上都是一致的。但由于您无法访问helper事件中的update,因此您需要先存储它。这可以在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'
            });
        }
    }

小提琴:http://jsfiddle.net/p0nft4mj/

答案 1 :(得分: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