views:

171

answers:

2

I had populated data in TreeView control. How will I drag a particular child node from a parent node and drop the dragged one to a DIV or any portion, using JQUERY ? I know in jquery, there are methods "draggable" and "droppable" to make this possible. But I want to drag a particular child node and drop it.

Or atleast How to fetch the text/id of a particular child node using jquery ? I hope I can drag,if I can fetch the child node

+2  A: 

If you have the following 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>

Add

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

To display the text of the dropped node.

You will need the jquery.ui libraries though.

If you plan to drag and drop a treenode with its child nodes you might be in for some fun as apparently a tree node is rendered as a table (for the parent) and a div with the children in. There's no div wrapping both.

Maybe you could override the RenderContents in a TreeView derived class and recursivly handle the rendering of the treenodes yourself but sounds like a lot of work just to wrap two elements.

Maybe a better choice would be using a JQuery plugin to render your treelist.

Stefaan
hi Stefaan...I tried this out. I can drag but some issues.I had passed "{helper:clone}" as parameter in "draggable". the issues are as follows : 1. Once I drag a node, the text displays twice while dragging.Same as the alert message. the alert shows twice because of the text showing twice while dragging2. After I drop the dragged node, a runtime script error occurs saying "originalTargetText.text is null or not an object".same as alert message, the error message also shows twice related to dragged node text showing twice.I think this was what I wanted. except the above issues.
Sreejesh Kumar
Here I had passed "helper:'clone'" as parameter in "draggable()" method where the node had shown twice, also the alert messages. And if I dont pass "helper:clone" at "draggable()" method, the node shows only once but each time i drag the node, the node text gets separated from the mouse pointer. I dont want to move the node.While I drag, I want that to be there in the TreeView itself and the node text should be displayed along with the mouse pointer while dragging. Also how to eliminate the checkbox while dragging ? And I want only the child nodes to be dragged since my work needs only this.
Sreejesh Kumar
Apparently the null reference error is only in IE even so use ui.draggable.text() instead of event.originalTarget.text. I'll have a look at the other issues if I find the time today.
Stefaan
+1  A: 

Ok I add this as another answer because the comment box is to small,

To hide/show an item while dragging you can use the start and stop events.

This example shows/hides the +/- (collapse/uncollapse) icon next to the treenode text while dragging but you can easily modify it to hide/show the checkboxes if present.

<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());
        }
    });
});

I'll try to have a look at the clone problem.

-- edit --

Apparently the clone problem is only in IE and is caused by the

 <NodeStyle CssClass="treeNode" />

In conjunction with

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

This puts the treeNode class not only on the "a" tag but also on the surrounding "td" tag. So by using the .treeNode selector the draggable method is executed twice ... This is not the case in FF.

You could solve this by just changing the selector in "#<%= TreeView1.ClientID%> a.treeNode" So with the afore mentioned aspx you would get the following script.

    $(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>

-- edit --

In answer to your comment:

To get the value of the dragged node you can use javascript string manipulation to filter it out of the href attribute (treenode renders the value in the href attr).

Your javascript in the drop function could look like the following. (still need to do some checking for null values ofcourse)

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

Or you can make it a little cleaner client-side by inheriting Treenode and wrap every Treenode by a div with a custom attribut in which you put your clientside id.

Your custom treenode could look like this

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");
    }        
}

Then in your aspx use (register you custom web control assembly first)

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

instead of

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

And your javascript stays nice and clean

alert($(ui.draggable).parent().attr("id"));
Stefaan
How will i retrieve the value of the dragged node ?
Sreejesh Kumar
Thanks Steffan.....Finally I got what I wanted.....Both Text and Value.
Sreejesh Kumar
One more thing Steffan! I want to drag only the child nodes. I dont have to drag the parent nodes. So how will I make only the child nodes draggable ? What should I do in the above jquery at draggable ?
Sreejesh Kumar
Did you get the ID by using a derived TreeNode or by filtering out of the href attribute? If you've done it through a derived treenode class you can easily check if the node has childnodes (base.ChildNodes.Count > 0) in the RenderPreText method and add a class in the surrounding div. Then change your JQuery selector for the draggable event accordingly.This is the way(= derived TreeNode) I would do it as I don't see any clean way to do it changing the draggable selecor without getting into some ugly string programming.
Stefaan