You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止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'
});

关键逻辑解释

  1. over事件处理:当拖拽元素悬停在Sortable列表上时,我们检查占位符的位置。如果占位符出现在首尾位置,就隐藏它,让用户直观知道这个位置不能放置。
  2. receive事件处理:当拖拽元素被放入列表后,立即获取它的索引。如果是首位(索引0)或末尾(索引等于当前列表长度-1),就移除这个元素,并让拖拽的辅助元素返回原位置,实现“无效放置”的效果。
  3. 通用配置函数:把重复的Sortable配置抽成函数,让代码更简洁易维护,后续有修改需求也能统一调整。

这样修改后,不管禁用项在列表的开头还是末尾,Draggable元素都无法放到首尾位置,完全符合你的需求。

内容的提问来源于stack exchange,提问作者袩邪薪邪泄芯褌 孝芯谢械胁

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:27:41