拖放一个子节点

Posted

技术标签:

【中文标题】拖放一个子节点【英文标题】:Drag and drop a child node 【发布时间】:2011-03-12 16:18:29 【问题描述】:

我在 TreeView 控件中填充了数据。如何使用 JQUERY 从父节点拖动特定子节点并将拖动的子节点拖放到 DIV 或任何部分?我知道在 jquery 中,有“可拖动”和“可放置”的方法使这成为可能。但我想拖动一个特定的子节点并放下它。

或至少如何使用 jquery 获取特定子节点的文本/ID?我希望我可以拖动,如果我可以获取子节点

【问题讨论】:

【参考方案1】:

如果你有以下aspx

<asp:TreeView ID="TreeView1" runat="server">
    <Nodes>
        <asp:TreeNode Text="Employees">
            <asp:TreeNode Text="HR" Value="SubClass1">
                <asp:TreeNode Text="Bradley" Value="ID-1234" />
                <asp:TreeNode Text="Whitney" Value="ID-5678" />
                <asp:TreeNode Text="Barbara" Value="ID-9101" />
            </asp:TreeNode>
            <asp:TreeNode Text="IT" Value="SubClass2">
                <asp:TreeNode Text="Jimmy" Value="ID-5587" />
                <asp:TreeNode Text="Samantha" Value="ID-5474" />
                <asp:TreeNode Text="Freddy" Value="ID-2001" />
            </asp:TreeNode>
        </asp:TreeNode>
    </Nodes>
    <NodeStyle CssClass="treeNode" />
</asp:TreeView>

添加

<script type="text/javascript">
    $(function () 
        $(".treeNode").draggable();
        $("#<%= TreeView1.ClientID%>").droppable(
            drop: function (event, ui) 
                alert(event.originalTarget.text);
            
        );
    );
</script>

显示被删除节点的文本。

不过,您将需要 jquery.ui 库。

如果您打算拖放一个带有子节点的树节点,您可能会觉得很有趣,因为显然树节点被呈现为一个表(对于父节点)和一个包含子节点的 div。没有 div 包装两个都。

也许您可以覆盖 TreeView 派生类中的 RenderContents 并自己递归处理树节点的呈现,但听起来像很多工作只是为了包装两个元素。

也许更好的选择是使用 JQuery 插件来呈现您的树列表。

【讨论】:

嗨 Stefaan...我试过了。我可以拖动但有一些问题。我已将“helper:clone”作为“可拖动”中的参数传递。问题如下: 1.一旦我拖动一个节点,拖动时文本显示两次。与警报消息相同。警报显示两次,因为拖动时文本显示两次 2. 放下拖动的节点后,出现运行时脚本错误,提示“originalTargetText.text 为空或不是对象”。与警报消息相同,错误消息也显示两次与显示两次的拖动节点文本有关。我想这就是我想要的。上述问题除外。 在这里,我在“draggable()”方法中传递了“helper:'clone'”作为参数,其中节点显示了两次,还有警报消息。如果我没有在“draggable()”方法中传递“helper:clone”,节点只会显示一次,但每次我拖动节点时,节点文本都会与鼠标指针分离。我不想移动节点。当我拖动时,我希望它出现在 TreeView 本身中,并且节点文本应该在拖动时与鼠标指针一起显示。另外如何在拖动时消除复选框?而且我只想拖动子节点,因为我的工作只需要这个。 显然空引用错误仅在 IE 中,即使使用 ui.draggable.text() 而不是 event.originalTarget.text。如果我今天有时间,我会看看其他问题。【参考方案2】:

好的,我将其添加为另一个答案,因为评论框太小,

要在拖动时隐藏/显示项目,您可以使用开始和停止事件。

此示例在拖动时显示/隐藏树节点文本旁边的 +/-(折叠/展开)图标,但您可以轻松修改它以隐藏/显示复选框(如果存在)。

<script type="text/javascript">
$(function () 
    $(".treeNode").draggable(
            start: function (event, ui) 

                var previousTd = $(this).parent().prev() ;
                $("img", previousTd).css("visibility", "hidden");
            ,
            stop: function (event, ui) 
                var previousTd = $(this).parent().prev();
                $("img", previousTd).css("visibility", "visible");
            );
    $("#<%= TreeView1.ClientID%>").droppable(
        drop: function (event, ui) 
            alert(ui.draggable.text());
        
    );
);

我会尝试看看克隆问题。

-- 编辑--

显然克隆问题仅在IE中,并且是由

 <NodeStyle CssClass="treeNode" />

结合

$(".treeNode").draggable(...

这将 treeNode 类不仅放在“a”标签上,而且放在周围的“td”标签上。所以通过使用 .treeNode 选择器,draggable 方法被执行了两次……这在 FF 中不是这样的。

您只需更改“# a.treeNode”中的选择器即可解决此问题 因此,使用上述 aspx,您将获得以下脚本。

    $(function () 
        $("#<%= TreeView1.ClientID%> a.treeNode").draggable(
            appendTo: 'body',
            helper: 'clone',
            start: function (event, ui) 

                var previousTd = $(this).parent().prev();
                $("img", previousTd).css("visibility", "hidden");
            ,
            stop: function (event, ui) 
                var previousTd = $(this).parent().prev();
                $("img", previousTd).css("visibility", "visible");
            ,
            zIndex: '100'
        );

        $("#<%= TreeView1.ClientID%>").droppable(
            drop: function (event, ui) 
                alert(ui.draggable.text());
            
        );
    );
</script>

-- 编辑--

回复您的评论:

要获取拖动节点的值,您可以使用 javascript 字符串操作将其从 href 属性中过滤掉(treenode 呈现 href attr 中的值)。

您在 drop 函数中的 javascript 可能如下所示。 (当然还需要检查空值)

var hrefParts = $(ui.draggable.context.href.split("\\"));
var nodeValue = hrefParts[hrefParts.length - 1];
nodeValue = nodeValue.substring(0, nodeValue.length - 2);
alert(nodeValue);                    

或者您可以通过继承 Treenode 并使用带有自定义属性的 div 包装每个 Treenode 来使其客户端更简洁,您可以在其中放置客户端 ID。

您的自定义树节点可能如下所示

public class WrappedTreeNode : TreeNode

    public string ClientValue  get; set; 

    protected override void RenderPreText(htmlTextWriter writer)
    
        writer.WriteBeginTag("div");
        //you can simply use the base.Value aswell here if you want them to be the same
        writer.WriteAttribute("id", ClientValue);
        base.RenderPreText(writer);
    

    protected override void RenderPostText(HtmlTextWriter writer)
    
        base.RenderPostText(writer);
        writer.WriteEndTag("div");
            

然后在你的 aspx 中使用(先注册你自定义的 web 控件程序集)

<ServerControls:WrappedTreeNode Text="Bradley" ClientValue="ID-1221"/>

而不是

<asp:TreeNode Text="Bradley" Value="ID-1221"/>

你的 javascript 保持干净整洁

alert($(ui.draggable).parent().attr("id"));

【讨论】:

我将如何检索拖动节点的值? 还有一件事斯特凡!我只想拖动子节点。我不必拖动父节点。那么我将如何只使子节点可拖动?在可拖动的上述 jquery 中我应该做什么? 您是通过使用派生的 TreeNode 还是通过过滤掉 href 属性来获得 ID 的?如果您通过派生的树节点类完成此操作,您可以在 RenderPreText 方法中轻松检查节点是否具有子节点(base.ChildNodes.Count > 0)并在周围的 div 中添加一个类。然后相应地更改可拖动事件的 JQuery 选择器。这就是我会这样做的方式(=派生的TreeNode),因为我看不到任何干净的方式来改变可拖动的选择器而不涉及一些丑陋的字符串编程。

以上是关于拖放一个子节点的主要内容,如果未能解决你的问题,请参考以下文章

ztree获取当前选中节点子节点id集合的方法(转载)

是元素节点的属性节点子节点

EasyUI tree 选中父节点子节点全部选中,选中子节点父节点不选中

如何从父 yaml 节点获取完整的 yaml 节点子对象?

如何同时更新不同的节点子节点firebase android

jQuery获取父节点子节点兄弟节点