如何阻止Draggable元素被放置到Sortable列表末尾?(jQuery UI)
解决方案:限制Draggable元素不能放置到Sortable列表的首尾位置
我明白你的问题了——当Sortable列表首尾是禁用项时,你希望拖拽过来的元素既不能放到第一个位置,也不能放到最后一个位置,但目前末尾的限制没生效。问题出在items和cancel选项只控制了列表内元素的排序行为,没处理外部拖拽元素的放置位置校验。
这里有个可靠的解决思路:利用Sortable的receive事件,在拖拽元素被放入列表时,立即检查它的位置,如果是首尾位置就取消这次放置操作;同时配合over事件控制占位符的显示,给用户明确的视觉反馈。
修改后的完整代码
HTML 部分
<h2>Example 1</h2> <h4>Sortable</h4> <ul class="sortable1"> <li class="ui-state-disabled">Item 1 disabled</li> <li class="ui-state-disabled">Item 2 disabled</li> <li>Item 3 not disabled</li> </ul> <h4>Draggable</h4> <ul class="draggable1"> <li>Item 1 to drag</li> <li>Item 2 to drag</li> <li>Item 3 to drag</li> </ul> <h2>Example 2</h2> <h4>Sortable</h4> <ul class="sortable2"> <li>Item 1 not disabled</li> <li class="ui-state-disabled">Item 2 disabled</li> <li class="ui-state-disabled">Item 3 disabled</li> </ul> <h4>Draggable</h4> <ul class="draggable2"> <li>Item 1 to drag</li> <li>Item 2 to drag</li> <li>Item 3 to drag</li> </ul> <style> .placeholder {border: 1px solid #ccc; height: 20px;} .ui-state-disabled {opacity: 0.5;} </style>
JavaScript 部分
// 通用的Sortable配置函数,减少重复代码 function setupSortable(selector) { $(selector).sortable({ tolerance: 'pointer', items: '*:not(".ui-state-disabled")', placeholder: 'placeholder', cancel: '.ui-state-disabled', // 拖拽元素悬停时,控制占位符是否显示 over: function(event, ui) { const placeholder = $(this).find('.placeholder'); const placeholderIndex = placeholder.index(); const listLength = $(this).children().length; // 如果占位符在首位(索引0)或末尾(索引等于列表长度-1),隐藏占位符 if (placeholderIndex === 0 || placeholderIndex === listLength - 1) { placeholder.hide(); } else { placeholder.show(); } }, // 拖拽元素被放入后,校验位置并取消非法放置 receive: function(event, ui) { const itemIndex = $(ui.item).index(); const listLength = $(this).children().length; // 如果元素被放到首位或末尾,移除它并让拖拽元素返回原位置 if (itemIndex === 0 || itemIndex === listLength - 1) { ui.item.remove(); ui.helper.remove(); ui.draggable.draggable('option', 'revert', true); } } }); } // 初始化两个Sortable列表 setupSortable('.sortable1'); setupSortable('.sortable2'); // 初始化Draggable列表 $('.draggable1 li, .draggable2 li').draggable({ revert: 'invalid', helper: 'clone', connectToSortable: '.sortable1, .sortable2', cancel: '.ui-state-disabled' });
关键逻辑解释
over事件处理:当拖拽元素悬停在Sortable列表上时,我们检查占位符的位置。如果占位符出现在首尾位置,就隐藏它,让用户直观知道这个位置不能放置。receive事件处理:当拖拽元素被放入列表后,立即获取它的索引。如果是首位(索引0)或末尾(索引等于当前列表长度-1),就移除这个元素,并让拖拽的辅助元素返回原位置,实现“无效放置”的效果。- 通用配置函数:把重复的Sortable配置抽成函数,让代码更简洁易维护,后续有修改需求也能统一调整。
这样修改后,不管禁用项在列表的开头还是末尾,Draggable元素都无法放到首尾位置,完全符合你的需求。
内容的提问来源于stack exchange,提问作者袩邪薪邪泄芯褌 孝芯谢械胁
相关产品推荐
相关产品推荐

