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

如何阻止jQuery UI Sortable嵌套容器移动并消除报错?

问题描述

我正在配置嵌套DIV结构的jQuery UI Sortable组件,需求是仅允许带有moveFile类的元素可拖拽,其余所有DIV都要禁止移动。目前示例里的MoveDocument可以正常拖拽,但我需要阻止带编号的容器(.fldrIcon元素)被拖拽,同时消除以下报错:

Error: {
"message": "HierarchyRequestError: Node.insertBefore: The new child is an ancestor of the parent",
"filename": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js",
"lineno": 2,
"colno": 0
}

复现步骤:点击编号左侧并向下拖拽,拖拽编号2及以上的元素时会触发该报错。

当前代码

JavaScript

$(document).ready(function () { 
    $(".moveFldr").sortable({
        connectWith: "div.moveFldr :not(.fldrIcon) :not(span)",
        placeholder: "placeHolder",
        cancel: ".fldrIcon, .voidDoc",
    });

    $(".fldrIcon").sortable("disable");
});

CSS

.fldrIcon:before {
    cursor: pointer;
    content: counter(folders);
}

.voidDoc {
    text-decoration: line-through;
    text-decoration-color: red;
}

#voidDoc { 
     background-color:#FFF;
     border-radius:5px;
     color:#000;
     display:none; 
     padding:5px;
     min-width:400px;
     min-height: 130px;
}

.voidedDoc, .newDoc, .oldDoc {
    text-decoration: none !important;
}

.placeHolder {
    border-style: dashed;
    border-color: #000;
    height: 15px;
}

.grnDot, .redDot, .ylwDot {
    height: 10px;
    width: 20px;
    border-color: #000;
    border-style: solid;
    border-width: 1px;
    border-radius: 50%;
    font-size: 10px;
    display:inline-block;
    text-align: center;
    padding-bottom: 10px;
}

.subFixField {
    font-weight: 700;
}

.fixField {
    text-align:center;
}

.grnDot {
    background-color: #5efc03;
    color: #000;
}

.redDot {
    background-color: #FF0000;
    color: #FFF;
}

.ylwDot {
    background-color: #ffff00;
    color: #000;
}

.fldrIcon {
    counter-increment: folders;
}

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
<div style="text-align:center;">
    <div class="inlineBlock moveFldr" style="text-align:left;">
        <div id="C1" class="moveFldr lnkItems" data-cid="1" style="padding-left:30px;">
            <div id="F1" class="fldrIcon contextMenu moveFldr">. Procedures for Suppliers</div>
            <div id="C2" class="moveFldr lnkItems " data-cid="2" style="padding-left:30px;">
                <div id="F2" class="fldrIcon contextMenu moveFldr">. Performance of Activates</div>
                <div id="L101" class="upDoc moveFile  fileIcon2 hideFile" style="margin-left: 15px;">MoveDocument</div>
                <div id="C3" class="moveFldr lnkItems " data-cid="3" style="padding-left:30px;">
                    <div id="F3" class="fldrIcon contextMenu moveFldr">. Verification Documents</div>
                    <div id="C4" class="moveFldr lnkItems " data-cid="4" style="padding-left:30px;">
                        <div id="F4" class="fldrIcon contextMenu moveFldr">. Performance Evaluation</div>
                    </div>
                    <div id="C5" class="moveFldr lnkItems " data-cid="5" style="padding-left:30px;">
                        <div id="F5" class="fldrIcon contextMenu moveFldr">. Verification Reports</div>
                    </div>
                    <div id="C6" class="moveFldr lnkItems " data-cid="6" style="padding-left:30px;">
                        <div id="F6" class="fldrIcon contextMenu moveFldr">. Testing Water</div>
                        <div id="C19" class="moveFldr lnkItems " data-cid="19" style="padding-left:30px;">
                            <div id="F19" class="fldrIcon contextMenu moveFldr">. 2022-2023</div>
                        </div>
                        <div id="C20" class="moveFldr lnkItems " data-cid="20" style="padding-left:30px;">
                            <div id="F20" class="fldrIcon contextMenu moveFldr">. 2023-2024</div>
                        </div>
                        <div id="C21" class="moveFldr lnkItems ">
                            <div id="F21" class="fldrIcon contextMenu moveFldr" style="padding-left:30px;">. 2024-2025</div>
                        </div>
                        <div id="C22" class="moveFldr lnkItems " data-cid="22" style="padding-left:30px;">
                            <div id="F22" class="fldrIcon contextMenu moveFldr">. 2025-2026</div>
                        </div>
                    </div>
                    <div id="C7" class="moveFldr lnkItems " data-cid="7" style="padding-left:30px;">
                        <div id="F7" class="fldrIcon contextMenu moveFldr" data-cid="7">. Supplier’s Certification</div>
                    </div>
                    <div id="C8" class="moveFldr lnkItems " data-cid="8" style="padding-left:30px;">
                        <div id="F8" class="fldrIcon contextMenu moveFldr">. Training Program</div>
                    </div>
                    <div id="C10" class="moveFldr lnkItems " data-cid="10" style="padding-left:30px;">
                        <div id="F10" class="fldrIcon contextMenu moveFldr">. Drug Testing</div>
                    </div>
                    <div id="C11" class="moveFldr lnkItems " data-cid="11" style="padding-left:30px;">
                        <div id="F11" class="fldrIcon contextMenu moveFldr">. Annual 3rd Party Audit</div>
                        <div id="C12" class="moveFldr lnkItems " data-cid="12" style="padding-left:30px;">
                            <div id="F12" class="fldrIcon contextMenu moveFldr" data-cid="12">. Corrective Action Reports</div>
                        </div>
                    </div>
                    <div id="C17" class="moveFldr lnkItems " data-cid="17" style="padding-left:30px;">
                        <div id="F17" class="fldrIcon contextMenu moveFldr">. Other Documents</div>
                    </div>
                    <div id="C9" class="moveFldr lnkItems " data-cid="9" style="padding-left:30px;">
                        <div id="F9" class="fldrIcon contextMenu moveFldr">. Analysis Review</div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
解决方案

问题根源是给所有.moveFldr元素都绑定了Sortable,包括嵌套容器和带编号的.fldrIcon,导致拖拽时DOM层级操作冲突,触发HierarchyRequestError;同时cancel配置没彻底阻止容器拖拽,反而因为嵌套Sortable实例互相干扰加剧了问题。

按以下方式修改代码:

$(document).ready(function () { 
    // 给所有.moveFldr容器绑定Sortable,但仅允许.moveFile元素拖拽
    $(".moveFldr").sortable({
        items: ".moveFile", // 核心:只指定moveFile类元素为可拖拽项
        connectWith: ".moveFldr", // 简化跨容器拖拽规则,按需保留
        placeholder: "placeHolder",
        cancel: ".fldrIcon, .voidDoc, .lnkItems" // 明确禁止容器类元素触发拖拽
    });
});

如果只需要特定层级的容器支持文件拖拽,可以更精准地选择目标容器:

// 仅给直接包含.moveFile的.moveFldr容器绑定Sortable
$(".moveFldr:has(.moveFile)").sortable({
    items: ".moveFile",
    placeholder: "placeHolder",
    cancel: ":not(.moveFile)" // 除了moveFile,其他元素都禁止拖拽
});

逻辑说明

  1. items: ".moveFile" 从根源上限定了可拖拽元素,直接阻止容器(包括带编号的.fldrIcon)被拖拽。
  2. 避免给嵌套DOM元素重复绑定Sortable,消除父/子容器同时触发Sortable逻辑导致的DOM插入层级冲突。
  3. 移除不必要的sortable("disable")调用,通过配置即可实现需求。

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 08:12:02