Loading ...
Sorry, an error occurred while loading the content.

Drag and drop in treeview

Expand Messages
  • Ajith Joseph
    Hi, Could you please tell me how can I add drag and drop utility in the tree control.
    Message 1 of 6 , May 23, 2006
    • 0 Attachment
      Hi,

      Could you please tell me how can I add drag and drop utility in the
      tree control.
    • Nige White
      I have my page working quite well now. Right now, you can drag TO the tree. Right clicking on a Menu node in the tree offers to create a new submenu node.
      Message 2 of 6 , May 23, 2006
      • 0 Attachment
        I have my page working quite well now. Right now, you can drag TO the
        tree. Right clicking on a Menu node in the tree offers to create a new
        submenu node. Right clicking on any non-root node offers to delete it.

        I plane to make tree nodes draggable inside the tree. I also plane to
        make them renameable.

        You'll need the following extra code in the YAHOO.widget.Node.prototype
        in treeview.js:

        /**
        * Inserts a node into the child collection before an existing node.
        *
        * @param node {Node} the new node
        * @param refNode {Node} the node to insert before
        * @return {Node} the child node
        */
        insertBefore: function(node, refNode)
        {
        if (refNode)
        {
        var refIndex = this.contains(refNode);
        if (refIndex != -1)
        {
        this.children.splice(refIndex, 0, node);
        if (refNode.previousSibling)
        refNode.previousSibling.nextSibling = node;
        node.previousSibling = refNode.previousSibling;
        node.nextSibling = refNode;
        refNode.previousSibling = node;
        this.tree.regNode(node);
        this.childrenRendered = false;
        }
        return node;
        }
        return this.appendChild(node);
        },

        /**
        * Inserts a node into the child collection after an existing node.
        *
        * @param node {Node} the new node
        * @param refNode {Node} the node to insert after
        * @return {Node} the child node
        */
        insertAfter: function(node, refNode)
        {
        if (refNode)
        {
        var refIndex = this.contains(refNode);
        if (refIndex != -1)
        {
        if (!refNode.nextSibling)
        return this.appendChild(node);
        this.children.splice(refIndex + 1, 0, node);
        refNode.nextSibling.previousSibling = node;
        node.previousSibling = refNode;
        node.nextSibling = refNode.nextSibling;
        refNode.nextSibling = node;
        this.tree.regNode(node);
        this.childrenRendered = false;
        }
        return node;
        }
        return this.appendChild(node);
        },

        /**
        * Returns true if the passed Node is a child of this Node
        *
        * @param node {Node} the Node to check
        * @return {boolean} The node index if the Node is a child of this
        Node, else -1.
        * @private
        */
        contains: function(node)
        {
        for (var i = 0; i < this.children.length; i++)
        if (this.children[i] == node)
        return i;
        return -1;
        },




        Then this extra code in dom.js:

        /**
        * Returns true of this Region is above (centre has a lower y coordinate)
        * than the passed Region.
        *
        * @param {YAHOO.util.Region} r The other Region, an element ID, an
        element, or an [x, y] array.
        * @return {boolean} true if this region is higher on the page than the
        other region
        */
        YAHOO.util.Region.prototype.isAbove = function(r)
        {
        var thisCentre = this.top + ((this.bottom - this.top) / 2);
        var otherCentre;
        if (typeof r == "number")
        otherCentre = r;
        else if (r.constructor == Array)
        otherCentre = r[1];
        else
        {
        if (!(r.top && r.bottom))
        r = YAHOO.util.Dom.getRegion(r)
        otherCentre = r.top + ((r.bottom - r.top) / 2);
        }
        return thisCentre < otherCentre;
        }
        YAHOO.util.Region.prototype.isBelow = function(r)
        {
        return !this.isAbove(r);
        }

        /**
        * Returns true of this Region is left of (centre has a lower x coordinate)
        * than the passed Region.
        *
        * @param {YAHOO.util.Region} r The other Region, an element ID, an
        element, or an [x, y] array.
        * @return {boolean} true if this region is further left on the page
        than the other region
        */
        YAHOO.util.Region.prototype.isLeftOf = function(r)
        {
        var thisCentre = this.left + ((this.right - this.left) / 2);
        var otherCentre;
        if (typeof r == "number")
        otherCentre = r;
        else if (r.constructor == Array)
        otherCentre = r[0];
        else
        {
        if (!(r.left && r.right))
        r = YAHOO.util.Dom.getRegion(r)
        otherCentre = r.left + ((r.right - r.left) / 2);
        }
        return thisCentre < otherCentre;
        }
        YAHOO.util.Region.prototype.isRightOf = function(r)
        {
        return !this.isLeftOf(r);
        }



        Then, put this html page into the examples/treeview directory:

        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
        <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
        <head>
        <title>Yahoo! UI Library - Tree Control</title>
        <script type="text/javascript" src="../../build/yahoo/yahoo.js"
        ></script>
        <script type="text/javascript"
        src="../../build/event/event.js"></script>
        <script type="text/javascript"
        src="../../build/dom/dom.js"></script>
        <script type="text/javascript"
        src="../../build/connection/connection.js"></script>
        <script type="text/javascript"
        src="../../build/animation/animation.js"></script>
        <script type="text/javascript"
        src="../../build/dragdrop/dragdrop.js"></script>
        <script type="text/javascript"
        src="../../build/treeview/treeview.js" ></script>
        <script type="text/javascript"
        src="../../build/container/container.js" ></script>
        <script type="text/javascript" src="../../build/menu/menu.js"
        ></script>
        <!-- CSS for Menu -->
        <style type="text/css">
        /*
        Copyright (c) 2006, Yahoo! Inc. All rights reserved.
        Code licensed under the BSD License:
        http://developer.yahoo.net/yui/license.txt
        */


        /* Menu styles */
        div.yuimenu {
        z-index:1;
        visibility:hidden;
        background-color:#d0d0d0;
        border: 2px solid;
        border-color: #f0f0f0 #909090 #909090 #f0f0f0;
        padding:1px;
        }


        /* MenuBar Styles */
        div.yuimenubar {
        background-color: #d0d0d0;
        border: 2px solid;
        border-color: #f0f0f0 #909090 #909090 #f0f0f0;
        padding: 1px 4px 1px 4px;
        }

        /*
        Application of "zoom:1" triggers "haslayout" in IE so that
        the module's
        body clears its floated elements
        */
        div.yuimenubar div.bd {
        zoom:1;
        }

        /*
        Clear the module body for other browsers
        */
        div.yuimenubar div.bd:after {
        content:'.';
        display:block;
        clear:both;
        visibility:hidden;
        height:0;
        }

        /* No downarrows */
        li.yuimenubaritem > img[alt="Collapsed. Click to expand."],
        li.yuimenubaritem > img[alt="Expanded. Click to collapse."]
        {
        display:none;
        }

        /* Matches the group title (H6) inside a Menu or MenuBar instance */
        div.yuimenu h6,
        div.yuimenubar h6 {
        font-size:100%;
        font-weight:normal;
        margin:0;
        }

        div.yuimenubar h6 {
        float:left;
        display:inline; /* Prevent margin doubling in IE */
        padding:4px 12px;
        border-width:0 1px 0 0;
        }

        div.yuimenu h6 {
        float:none;
        display:block;
        border-width:1px 0 0 0;
        padding:5px 10px 0 10px;
        }

        /* Matches the UL inside a Menu or MenuBar instance */
        div.yuimenubar ul {
        list-style-type:none;
        margin:0;
        padding:0;
        overflow:hidden;
        }

        div.yuimenu ul {
        list-style-type:none;
        margin:0;
        padding:0px 0px 2px 0px;
        }

        div.yuimenu ul.first,
        div.yuimenu ul.hastitle,
        div.yuimenu h6.first {
        border-width:0;
        }


        /* MenuItem and MenuBarItem styles */
        div.yuimenubar li
        {
        padding:0px;
        }

        div.yuimenu li
        {
        padding:2px 0px 2px 0px;
        }

        div.yuimenu li,
        div.yuimenubar li {
        color: #000000;
        cursor: default;
        text-decoration: none;
        white-space:nowrap;
        text-align:left;
        }

        div.yuimenu li.yuimenuitem {
        }

        div.yuimenu li li,
        div.yuimenubar li li {
        font-size:100%;
        }


        /* Matches the help text for a MenuItem instance */
        div.yuimenu li em {
        font-style:normal;
        margin:0 0 0 40px;
        }

        div.yuimenu a em {
        margin:0;
        }

        li.yuimenubaritem > a {
        padding:0px 8px 0px 8px;
        display:table-cell;
        line-height:1.5em;
        border:1px solid #d0d0d0;
        }

        li.yuimenuitem > a {
        padding:0px 8px 0px 8px;
        border:none;
        }

        li.yuimenuitem > a,
        li.yuimenubaritem > a {
        /*
        "zoom:1" triggers "haslayout" in IE to ensure that the
        mouseover and
        mouseout events bubble to the parent LI in IE.
        */
        zoom:1;
        color:#000;
        text-decoration:none;
        outline:none!important;
        }

        /* Mouse hovering over MenuBarItem: Outset border */
        li.yuimenubaritem > a:hover {
        border-color: #f0f0f0 #909090 #909090 #f0f0f0;
        color:#000000;
        }

        /* Mouse hovering over MenuBar: white text on blue background */
        li.yuimenuitem.mouseover {
        border:none;
        background-color: #000070;
        color:#ffffff;
        }

        /* //\\ Patch from Todd.
        //\\ Did not make a difference */
        div.yuimenu li.yuimenuitem img {
        margin:0 -16px 0 10px;
        border:0;
        }

        /* This (less pecific) rule was already present. (The above one
        shou;d be the standard)
        Matches the sub menu indicator for a MenuItem instance
        div.yuimenu li img {
        margin:0 -16px 0 10px;
        border:0;
        }*/

        div.yuimenu li.hassubmenu,
        div.yuimenu li.hashelptext {
        text-align:right;
        }

        div.yuimenu li.hassubmenu a.hassubmenu,
        div.yuimenu li.hashelptext a.hashelptext {
        float:left;
        display:inline; /* Prevent margin doubling in IE */
        text-align:left;
        }


        /* Matches focused and selected MenuItem instances */

        div.yuimenubar li.yuimenubaritem.selected > a {
        background-color: #a0a0a0;
        border-color: #909090 #f0f0f0 #f0f0f0 #909090!important;
        color:#000000;
        }

        div.yuimenu li.yuimenuitem.selected {
        background-color: #000070;
        color:#ffffff;
        }

        div.yuimenu li.selected a.selected,
        div.yuimenu li.selected em.selected,
        div.yuimenubar li.selected a.selected {
        color:#fff;
        }


        /* Matches disabled MenuItem instances */
        div.yuimenu li.disabled,
        div.yuimenubar li.disabled {
        cursor:default;
        }

        div.yuimenu li.disabled a.disabled,
        div.yuimenu li.disabled em.disabled,
        div.yuimenubar li.disabled a.disabled {
        color:#b9b9b9;
        cursor:default;
        }

        div.yuimenubar li.yuimenubaritem {
        float:left;
        display:inline; /* Prevent margin doubling in IE */
        margin:0;
        }

        div.yuimenubar li.yuimenubaritem.first {
        border-width:0;
        }

        div.yuimenubar li.yuimenubaritem img {
        margin:0 0 0 10px;
        vertical-align:middle;
        }
        </style>
        <link rel="stylesheet" type="text/css" href="css/screen.css" />
        <link rel="stylesheet" type="text/css" href="css/local/tree.css" />
        <style type="text/css">
        #menuContainer {
        float:left;
        border:2px inset;
        overflow:auto;
        }

        #componentContainer {
        float:left;
        border:2px inset;
        overflow:auto;
        }

        .Component {
        background-color:lightblue;
        border-bottom:1px groove;
        }
        </style>
        <script type="text/javascript">
        // Starting with the given node, find the nearest containing
        element
        // with the specified tag name and optionally class name.
        function getAncestorWithClass(node, tagName, className)
        {
        var lcTag = tagName.toLowerCase();
        while (node != null)
        {
        if (node.tagName != null && node.tagName.toLowerCase()
        == lcTag)
        {
        if (typeof(className) != "undefined")
        {
        if (YAHOO.util.Dom.hasClass(node, className))
        {
        return node;
        }
        }
        else
        {
        return node;
        }
        }
        node = node.parentNode;
        }

        return node;
        }

        var tree;
        function onWindowLoad()
        {
        tree = new DDTreeView("menuTree");
        var menuBar = new YAHOO.widget.TextNode({label:"Nigel's
        Menu", href:"#"}, tree.getRoot(), false);
        menuBar.canHaveChildren = true;
        menuBar.data =
        {className:"com.fcl.greenfield.entity.Menu", uuid:0};
        menuBar.expand();
        tree.draw();

        // Activate the components...
        var c = new Component("Component:1", "menuTree")
        c.copy = true;
        c.data =
        {className:"com.fcl.greenfield.entity.Component", uuid:1};
        c = new Component("Component:2", "menuTree")
        c.copy = true;
        c.data =
        {className:"com.fcl.greenfield.entity.Component", uuid:2};
        c = new Component("Component:3", "menuTree")
        c.copy = true;
        c.data =
        {className:"com.fcl.greenfield.entity.Component", uuid:3};
        }

        DDTreeView = function(id)
        {
        this.init(id);
        this.insertHighlight = document.createElement("div");
        this.insertHighlight.style.display = "none";
        this.insertHighlight.style.position = "absolute";
        this.insertHighlight.style.backgroundColor =
        "activecaption";
        this.insertHighlight.style.height = "2px";
        this.insertHighlight.style.width = "45px";
        document.body.appendChild(this.insertHighlight);
        this.newNodeCount = 0;
        }
        DDTreeView.prototype = new YAHOO.widget.TreeView();
        DDTreeView.prototype.superDraw = DDTreeView.prototype.draw;

        DDTreeView.prototype.draw = function()
        {
        // Call superclass's draw()
        this.superDraw();

        // Make the tree droppable on.
        new YAHOO.util.DDTarget(this.id, "menuTree").menuTree =
        this;

        // Create ContextMenu
        this.contextMenu = new
        YAHOO.widget.ContextMenu("contextMenu", {trigger:this.id});
        this.createMenuItem = new
        YAHOO.widget.ContextMenuItem("New Submenu");

        this.createMenuItem.clickEvent.subscribe(this.createNewMenu, this, true);
        this.contextMenu.addItem(this.createMenuItem);
        this.deleteMenuItem = new
        YAHOO.widget.ContextMenuItem("Delete");

        this.deleteMenuItem.clickEvent.subscribe(this.deleteMenu, this, true);
        this.contextMenu.addItem(this.deleteMenuItem);

        // Add a "move" event handler to the context menu

        this.contextMenu.beforeShowEvent.subscribe(this.onMoveContextMenu, this,
        true);
        this.contextMenu.render(document.body);
        }

        // Given a target DOM element, work up to find its label,
        // extract the node index, and look it up in the tree.
        DDTreeView.prototype.getTreeNode = function(target)
        {
        var result = getAncestorWithClass(target, "a", "ygtvlabel");
        if (result && result.id)
        {
        result = YAHOO.widget.TreeView.getNode(this.id,
        parseInt(/ygtvlabelel(\d+)/.exec(result.id)[1]));
        }
        return result;
        }

        DDTreeView.prototype.onMoveContextMenu = function(e, o)
        {
        var target =
        this.getTreeNode(this.contextMenu.contextEventTarget);
        if (target)
        {
        // Disable creation if we clicked on a node that
        can't have children
        this.createMenuItem.cfg.setProperty("disabled",
        !target.canHaveChildren);

        // Disable deletion if we clicked on the top level Menu.
        this.deleteMenuItem.cfg.setProperty("disabled",
        (target.parent == this.getRoot()));
        }
        else
        {
        this.contextMenu.cfg.applyConfig({visible:false });
        }
        YAHOO.util.Event.preventDefault(e);
        }

        // Called from the context menu in the scope of the MenuTree
        DDTreeView.prototype.createNewMenu = function(e, o)
        {
        var target =
        this.getTreeNode(this.contextMenu.contextEventTarget);
        if (target)
        {
        target.collapse();
        var submenu = new YAHOO.widget.TextNode({label: "New
        Menu " + (++this.newNodeCount), href:"#"}, target, false);
        submenu.canHaveChildren = true;
        submenu.data =
        {className:"com.fcl.greenfield.entity.Menu"}
        target.expand();
        }
        this.contextMenu.hide();
        }

        // Called from the context menu in the scope of the MenuTree
        DDTreeView.prototype.deleteMenu = function(e, o)
        {
        var target =
        this.getTreeNode(this.contextMenu.contextEventTarget);
        if (target)
        {
        target.parent.collapse();
        this.removeNode(target);
        target.parent.expand();
        }
        this.contextMenu.hide();
        }

        // Returns the lowest target node at the event's coordinates
        DDTreeView.prototype.getInsertionPoint = function(e)
        {
        this.insertHighlight.style.display = "none";
        var p = new
        YAHOO.util.Point(YAHOO.util.Event.getPageX(e),YAHOO.util.Event.getPageY(e));
        var c = this.getRoot().children;
        for (var i = 0; i < c.length; i++)
        {
        var result = this._getInsertionPoint(c[i], p);
        if (result)
        return result;
        }
        }

        /** Returns an object representing the target node position
        at the event's coordinates.

        The object is {root:nodeToInsertInto
        beforeNode|afterNode:reference node to
        insert before or after}
        */
        DDTreeView.prototype._getInsertionPoint = function(node, p)
        {
        // The region occupied by the label element.
        var labelRegion =
        YAHOO.util.Region.getRegion(node.getLabelEl());

        if (node.canHaveChildren)
        {
        // The element containing child nodes.
        var childElement = node.getChildrenEl();

        // Get the region occupied by the child nodes.
        var childRegion =
        YAHOO.util.Region.getRegion(childElement);

        // Get the region occupied by the whole root line.
        Ensure it's as wide as the tree
        var rootRegion =
        YAHOO.util.Region.getRegion(childElement.previousSibling);
        var treeRegion =
        YAHOO.util.Region.getRegion(node.tree.getRoot().getEl());
        rootRegion.left = treeRegion.left;
        rootRegion.right = treeRegion.right;

        // If we're over the label, we're inserting either at
        the top,
        // or, if it's a collapsed node and we're below its
        centre line,
        // below it.
        if (rootRegion.contains(p))
        {
        this.insertHighlight.style.top =
        (labelRegion.bottom + 5) + "px";
        this.insertHighlight.style.left =
        (labelRegion.left + 17) + "px";
        this.insertHighlight.style.display = "";

        // If the node is expanded, we're inserting
        before its first child.
        if (node.expanded)
        return {root:node, beforeNode:node.children[0]};
        else
        {
        // If the node is collapsed, then decide
        whether to insert
        // AFTER it, or INTO it.
        if (!node.parent.isRoot())
        {
        // Hovering within 4 pixels of the bottom
        - insert AFTER it
        if (p.top > (rootRegion.bottom - 5))
        {
        this.insertHighlight.style.left =
        labelRegion.left + "px";
        return {root:node.parent,
        afterNode:node};
        }

        // Insert INTO it: Hide insertion point bar
        this.insertHighlight.style.display = "none";
        }

        // Unless it's a top level, in which case
        INTO it.
        return {root:node, beforeNode:null};
        }
        }

        else if (childRegion.contains(p))
        {
        // var result;
        for (var i = 0; i < node.children.length; i++)
        {
        var result =
        this._getInsertionPoint(node.children[i], p);
        if (result)
        return result;
        }
        }
        }

        // We're hovering over a leaf node.
        else
        {
        var e = YAHOO.util.Region.getRegion(node.getEl());
        if (e.contains(p))
        {
        this.insertHighlight.style.left =
        labelRegion.left + "px";
        this.insertHighlight.style.display = "";
        if (p.isAbove(e))
        {
        prevNode = node.previousSibling;
        if (!prevNode)
        prevNode = node.parent;
        this.insertHighlight.style.top =
        (YAHOO.util.Region.getRegion(prevNode.getLabelEl()).bottom + 5) + "px";
        return {root:node.parent, beforeNode:node};
        }
        else
        {
        this.insertHighlight.style.top =
        (labelRegion.bottom + 5) + "px";
        return {root:node.parent, afterNode:node};
        }
        }
        }
        this.insertHighlight.style.display = "none";
        }

        DDTreeView.prototype.insertTextNodeBefore = function(label,
        refNode, expanded)
        {
        var root = refNode.parent;
        var node = new
        YAHOO.widget.TextNode({label:this.getEl().innerHTML, href:"#"}, root,
        false);
        this.removeNode(node);
        root.insertBefore(node, refNode);
        return node;
        }

        DDTreeView.prototype.insertTextNodeAfter = function(label,
        refNode, expanded)
        {
        var root = refNode.parent;
        var node = new
        YAHOO.widget.TextNode({label:this.getEl().innerHTML, href:"#"}, root,
        false);
        this.removeNode(node);
        root.insertAfter(node, refNode);
        return node;
        }

        /**
        Extends DDProxy to allow copying of data.
        */
        var Component = function(id, sGroup)
        {
        this.copy = false;
        this.init(id, sGroup);
        this.initFrame();
        this.selectedTarget = null;
        this.isTarget = false;
        };
        Component.prototype = new YAHOO.util.DDProxy();

        Component.prototype.initFrame = function()
        {
        if (!Component.frameDiv)
        {
        if (!document || !document.body)
        {
        _this = this;
        setTimeout(function()
        {
        Component.prototype.initFrame.call(_this)
        }, 50);
        return;
        }
        this.setDragElId("componentProxy");
        Component.frameDiv = document.createElement("div");
        Component.frameDiv.id = "componentProxy";
        var s = Component.frameDiv.style;
        s.position = "absolute";
        s.visibility = "hidden";
        s.border = "none";
        s.zIndex = 999;
        document.body.appendChild(Component.frameDiv);
        }
        this.useAbsMath = true;
        };

        Component.prototype.getDragEl = function()
        {
        return Component.frameDiv;
        }

        Component.prototype.showFrame = function(iPageX, iPageY)
        {
        var el = this.getEl();
        var dragEl = Component.frameDiv;
        YAHOO.util.Dom.setStyle(dragEl, "opacity", 0.5);
        dragEl.className = el.className;
        dragEl.innerHTML = el.innerHTML;
        var s = dragEl.style;
        s.width = parseInt(el.offsetWidth, 10) + "px";
        s.height = parseInt(el.offsetHeight, 10) + "px";
        this.setDragElPos(iPageX, iPageY);
        s.visibility = "";
        document.body.style.cursor = "no-drop";
        };

        Component.prototype.onDragEnter = function(e, id)
        {
        document.body.style.cursor = "copy";
        };

        Component.prototype.onDragOut = function()
        {
        document.body.style.cursor = "no-drop";
        if (this.selectedTarget)
        this.selectedTarget.style.backgroundColor = "";
        tree.insertHighlight.style.display = "none";
        };

        Component.prototype.b4EndDrag = function()
        {
        this.getDragEl().style.visibility = "hidden";
        if (this.selectedTarget)
        this.selectedTarget.style.backgroundColor = "";
        document.body.style.cursor = "";
        };

        Component.prototype.onDragOver = function(e, id)
        {
        var menuTree = ((typeof id == "string") ?
        YAHOO.util.DragDropMgr.getDDById(id) : id[0]).menuTree;
        var insertionPoint = menuTree.getInsertionPoint(e);
        if (insertionPoint)
        {
        var el = insertionPoint.root.getLabelEl();
        if (this.selectedTarget && (this.selectedTarget != el))
        {
        this.selectedTarget.style.backgroundColor = "";
        }
        this.selectedTarget = el;
        this.selectedTarget.style.backgroundColor = "#ccddcc";
        }
        }

        Component.prototype.onDragDrop = function(e, id)
        {
        var menuTree = ((typeof id == "string") ?
        YAHOO.util.DragDropMgr.getDDById(id) : id[0]).menuTree;
        var insertionPoint = menuTree.getInsertionPoint(e);
        if (insertionPoint)
        {
        if (insertionPoint.afterNode)
        {
        var n = new
        YAHOO.widget.TextNode({label:this.getEl().innerHTML, href:"#"},
        insertionPoint.root, false);
        menuTree.removeNode(n);
        insertionPoint.root.insertAfter(n,
        insertionPoint.afterNode);
        }
        else
        {
        var n = new
        YAHOO.widget.TextNode({label:this.getEl().innerHTML, href:"#"},
        insertionPoint.root, false);
        menuTree.removeNode(n);
        insertionPoint.root.insertBefore(n,
        insertionPoint.beforeNode);
        }
        n.data = this.data;
        insertionPoint.root.refresh();

        // We've moved, not copied, so remove the original
        node, and clear it's DragDrop
        if (!this.copy)
        {
        var el = this.getDragEl();
        el.parent.removeChild(el);
        this.unreg();
        }

        }
        };

        // Don't remove the original node.
        Component.prototype.endDrag = function()
        {
        tree.insertHighlight.style.display = "none";
        };

        // Add a "load" handler for the window
        YAHOO.util.Event.addListener(window, "load", onWindowLoad);

        </script>
        </head>
        <body>
        <form id="mainForm">
        <div id="menuContainer"
        style="height:400px;width:300px;margin-right:10px;overflow:auto">
        <a href="javascript:tree.expandAll()">Expand all</a>
        <a href="javascript:tree.collapseAll()">Collapse all</a>
        <div id="menuTree"></div>
        </div>
        <div id="componentContainer" style="height:400px;width:300px">
        <div style="text-align:center">Components</div>
        <div id="components">
        <div class="Component" id="Component:1">Languages</div>
        <div class="Component" id="Component:2">Countries</div>
        <div class="Component" id="Component:3">Time zones</div>
        </div>
        </form>
        </body>
        </html>

        _____________________________________________________________________
        This message has been checked for all known viruses. Virus scanning
        powered by Messagelabs http://www.messagelabs.com For more information
        e-mail : hostmaster@...
      • Nige White
        OK, I have something pretty decent working at https://secure0.forward-comp.co.uk/yui/examples/treeview/fcl.html I haven t fully tested it, but it seems OK. I
        Message 3 of 6 , May 25, 2006
        • 0 Attachment
          OK, I have something pretty decent working at
          https://secure0.forward-comp.co.uk/yui/examples/treeview/fcl.html

          I haven't fully tested it, but it seems OK.

          I have a DDTreeView object which extends TreeView. It holds a DDTarget
          whose onDragEnter, onDragOver, onDragDrop and onDragOut call the
          equivalent functions on DDTreeView, sp that the DDTreeView can decide
          how to handle all these events in the correct way. DDTreeView handles
          everything, it's both a TreeView, and a drop target.

          This means that the *recipient* , the DDTreeView gets to specify what
          happens on drag over (complex highlighting algorithm), and how the drop
          occurs. In the case of a DDTreeView, it obviously has to create a new
          TextNode. It also makes that text node draggable.

          I also have a Draggable object which is a lot like DDProxy, but it's a
          bit better. showElement() is more sophisticated. It clones the internal
          structure of the node being dragged (and creates carrier elements around
          those internals, if say you are dragging a table row. It will copy the
          contents (a collection of <td>s) into a row in a table in the dragEl. If
          you are dragging a <td>, it will contain that correctly.

          The Draggable's onDragEnter, onDragOver, onDragDrop, and onDragOut, all
          call the target's equivalent of these functions to inform the target
          about the event, so that the target can handle it correctly. The thing
          *being dragged* should not get to fiddle with things - it should present
          itself to the target, and the target accepts or rejects it.

          I think this is getting towards being reusable, and more generalized.

          Using this pattern, you should be able to drag a Draggable to anything,
          and as long as that has implemented those 4 methods, it should be
          droppable on, and handle things correctly.

          Nige

          _____________________________________________________________________
          This message has been checked for all known viruses. Virus scanning
          powered by Messagelabs http://www.messagelabs.com For more information
          e-mail : hostmaster@...
        • asundlihardig
          Hi Is there anyone who might have experience on using drag and drop in treeview? I want to be able to move nodes around in the tree. Is this possible? Best
          Message 4 of 6 , Jan 31, 2007
          • 0 Attachment
            Hi

            Is there anyone who might have experience on using drag and drop in treeview?

            I want to be able to move nodes around in the tree.

            Is this possible?

            Best regards
            Alexander
          • Nige White
            The imminent (next couple of weeks) release of the yui-ext library will have a D/D enabled Tree control. It is possible to use it now by downloading an alpha
            Message 5 of 6 , Feb 1, 2007
            • 0 Attachment
              The imminent (next couple of weeks) release of the yui-ext library will
              have a D/D enabled Tree control. It is possible to use it now by
              downloading an alpha version.

              http://www.yui-ext.com/

              You'll need to be a fairly advanced JS programmer to use this library.
              But I assume you are because you are talking about using D/D in your
              project.

              Please read the examples in the blog from September onwards which
              contain detailed, worked examples of using the library to get a feel of
              how it works.

              Also, use the DOCUMENTATION link.

              asundlihardig wrote:

              > Hi
              >
              > Is there anyone who might have experience on using drag and drop in
              > treeview?
              >
              > I want to be able to move nodes around in the tree.
              >
              > Is this possible?
              >
              > Best regards
              > Alexander
              >
              >
              > - -
              > Scanned for viruses.



              - -
              Forward Computers Limited is a company registered in England and Wales with company number 3249628, VAT Number 416458349. Registered office address : Forward House, 161 Glaisdale Drive West, Nottingham, NG8 4GY

              This email has been scanned for viruses by Messagelabs.
            • harrierdh
              Try this function expandAllNode() { oCurrentTextNode.expandAll(); oCurrentTextNode.expand(); } function collapseAllNode() { oCurrentTextNode.collapseAll();
              Message 6 of 6 , May 31, 2007
              • 0 Attachment
                Try this
                function expandAllNode()
                {
                oCurrentTextNode.expandAll();
                oCurrentTextNode.expand();
                }

                function collapseAllNode()
                {
                oCurrentTextNode.collapseAll();
                oCurrentTextNode.collapse();
                }




                --- In ydn-javascript@yahoogroups.com, Nige White <nigelw@...> wrote:
                >
                > I have my page working quite well now. Right now, you can drag TO
                the
                > tree. Right clicking on a Menu node in the tree offers to create a
                new
                > submenu node. Right clicking on any non-root node offers to delete
                it.
                >
                > I plane to make tree nodes draggable inside the tree. I also plane
                to
                > make them renameable.
                >
                > You'll need the following extra code in the
                YAHOO.widget.Node.prototype
                > in treeview.js:
                >
                > /**
                > * Inserts a node into the child collection before an existing
                node.
                > *
                > * @param node {Node} the new node
                > * @param refNode {Node} the node to insert before
                > * @return {Node} the child node
                > */
                > insertBefore: function(node, refNode)
                > {
                > if (refNode)
                > {
                > var refIndex = this.contains(refNode);
                > if (refIndex != -1)
                > {
                > this.children.splice(refIndex, 0, node);
                > if (refNode.previousSibling)
                > refNode.previousSibling.nextSibling = node;
                > node.previousSibling = refNode.previousSibling;
                > node.nextSibling = refNode;
                > refNode.previousSibling = node;
                > this.tree.regNode(node);
                > this.childrenRendered = false;
                > }
                > return node;
                > }
                > return this.appendChild(node);
                > },
                >
                > /**
                > * Inserts a node into the child collection after an existing
                node.
                > *
                > * @param node {Node} the new node
                > * @param refNode {Node} the node to insert after
                > * @return {Node} the child node
                > */
                > insertAfter: function(node, refNode)
                > {
                > if (refNode)
                > {
                > var refIndex = this.contains(refNode);
                > if (refIndex != -1)
                > {
                > if (!refNode.nextSibling)
                > return this.appendChild(node);
                > this.children.splice(refIndex + 1, 0, node);
                > refNode.nextSibling.previousSibling = node;
                > node.previousSibling = refNode;
                > node.nextSibling = refNode.nextSibling;
                > refNode.nextSibling = node;
                > this.tree.regNode(node);
                > this.childrenRendered = false;
                > }
                > return node;
                > }
                > return this.appendChild(node);
                > },
                >
                > /**
                > * Returns true if the passed Node is a child of this Node
                > *
                > * @param node {Node} the Node to check
                > * @return {boolean} The node index if the Node is a child of
                this
                > Node, else -1.
                > * @private
                > */
                > contains: function(node)
                > {
                > for (var i = 0; i < this.children.length; i++)
                > if (this.children[i] == node)
                > return i;
                > return -1;
                > },
                >
                >
                >
                >
                > Then this extra code in dom.js:
                >
                > /**
                > * Returns true of this Region is above (centre has a lower y
                coordinate)
                > * than the passed Region.
                > *
                > * @param {YAHOO.util.Region} r The other Region, an element ID, an
                > element, or an [x, y] array.
                > * @return {boolean} true if this region is higher on the page than
                the
                > other region
                > */
                > YAHOO.util.Region.prototype.isAbove = function(r)
                > {
                > var thisCentre = this.top + ((this.bottom - this.top) / 2);
                > var otherCentre;
                > if (typeof r == "number")
                > otherCentre = r;
                > else if (r.constructor == Array)
                > otherCentre = r[1];
                > else
                > {
                > if (!(r.top && r.bottom))
                > r = YAHOO.util.Dom.getRegion(r)
                > otherCentre = r.top + ((r.bottom - r.top) / 2);
                > }
                > return thisCentre < otherCentre;
                > }
                > YAHOO.util.Region.prototype.isBelow = function(r)
                > {
                > return !this.isAbove(r);
                > }
                >
                > /**
                > * Returns true of this Region is left of (centre has a lower x
                coordinate)
                > * than the passed Region.
                > *
                > * @param {YAHOO.util.Region} r The other Region, an element ID, an
                > element, or an [x, y] array.
                > * @return {boolean} true if this region is further left on the
                page
                > than the other region
                > */
                > YAHOO.util.Region.prototype.isLeftOf = function(r)
                > {
                > var thisCentre = this.left + ((this.right - this.left) / 2);
                > var otherCentre;
                > if (typeof r == "number")
                > otherCentre = r;
                > else if (r.constructor == Array)
                > otherCentre = r[0];
                > else
                > {
                > if (!(r.left && r.right))
                > r = YAHOO.util.Dom.getRegion(r)
                > otherCentre = r.left + ((r.right - r.left) / 2);
                > }
                > return thisCentre < otherCentre;
                > }
                > YAHOO.util.Region.prototype.isRightOf = function(r)
                > {
                > return !this.isLeftOf(r);
                > }
                >
                >
                >
                > Then, put this html page into the examples/treeview directory:
                >
                > <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                > "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
                > <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
                > <head>
                > <title>Yahoo! UI Library - Tree Control</title>
                > <script type="text/javascript"
                src="../../build/yahoo/yahoo.js"
                > ></script>
                > <script type="text/javascript"
                > src="../../build/event/event.js"></script>
                > <script type="text/javascript"
                > src="../../build/dom/dom.js"></script>
                > <script type="text/javascript"
                > src="../../build/connection/connection.js"></script>
                > <script type="text/javascript"
                > src="../../build/animation/animation.js"></script>
                > <script type="text/javascript"
                > src="../../build/dragdrop/dragdrop.js"></script>
                > <script type="text/javascript"
                > src="../../build/treeview/treeview.js" ></script>
                > <script type="text/javascript"
                > src="../../build/container/container.js" ></script>
                > <script type="text/javascript"
                src="../../build/menu/menu.js"
                > ></script>
                > <!-- CSS for Menu -->
                > <style type="text/css">
                > /*
                > Copyright (c) 2006, Yahoo! Inc. All rights reserved.
                > Code licensed under the BSD License:
                > http://developer.yahoo.net/yui/license.txt
                > */
                >
                >
                > /* Menu styles */
                > div.yuimenu {
                > z-index:1;
                > visibility:hidden;
                > background-color:#d0d0d0;
                > border: 2px solid;
                > border-color: #f0f0f0 #909090 #909090 #f0f0f0;
                > padding:1px;
                > }
                >
                >
                > /* MenuBar Styles */
                > div.yuimenubar {
                > background-color: #d0d0d0;
                > border: 2px solid;
                > border-color: #f0f0f0 #909090 #909090 #f0f0f0;
                > padding: 1px 4px 1px 4px;
                > }
                >
                > /*
                > Application of "zoom:1" triggers "haslayout" in IE so
                that
                > the module's
                > body clears its floated elements
                > */
                > div.yuimenubar div.bd {
                > zoom:1;
                > }
                >
                > /*
                > Clear the module body for other browsers
                > */
                > div.yuimenubar div.bd:after {
                > content:'.';
                > display:block;
                > clear:both;
                > visibility:hidden;
                > height:0;
                > }
                >
                > /* No downarrows */
                > li.yuimenubaritem > img[alt="Collapsed. Click to expand."],
                > li.yuimenubaritem > img[alt="Expanded. Click to collapse."]
                > {
                > display:none;
                > }
                >
                > /* Matches the group title (H6) inside a Menu or MenuBar
                instance */
                > div.yuimenu h6,
                > div.yuimenubar h6 {
                > font-size:100%;
                > font-weight:normal;
                > margin:0;
                > }
                >
                > div.yuimenubar h6 {
                > float:left;
                > display:inline; /* Prevent margin doubling in IE */
                > padding:4px 12px;
                > border-width:0 1px 0 0;
                > }
                >
                > div.yuimenu h6 {
                > float:none;
                > display:block;
                > border-width:1px 0 0 0;
                > padding:5px 10px 0 10px;
                > }
                >
                > /* Matches the UL inside a Menu or MenuBar instance */
                > div.yuimenubar ul {
                > list-style-type:none;
                > margin:0;
                > padding:0;
                > overflow:hidden;
                > }
                >
                > div.yuimenu ul {
                > list-style-type:none;
                > margin:0;
                > padding:0px 0px 2px 0px;
                > }
                >
                > div.yuimenu ul.first,
                > div.yuimenu ul.hastitle,
                > div.yuimenu h6.first {
                > border-width:0;
                > }
                >
                >
                > /* MenuItem and MenuBarItem styles */
                > div.yuimenubar li
                > {
                > padding:0px;
                > }
                >
                > div.yuimenu li
                > {
                > padding:2px 0px 2px 0px;
                > }
                >
                > div.yuimenu li,
                > div.yuimenubar li {
                > color: #000000;
                > cursor: default;
                > text-decoration: none;
                > white-space:nowrap;
                > text-align:left;
                > }
                >
                > div.yuimenu li.yuimenuitem {
                > }
                >
                > div.yuimenu li li,
                > div.yuimenubar li li {
                > font-size:100%;
                > }
                >
                >
                > /* Matches the help text for a MenuItem instance */
                > div.yuimenu li em {
                > font-style:normal;
                > margin:0 0 0 40px;
                > }
                >
                > div.yuimenu a em {
                > margin:0;
                > }
                >
                > li.yuimenubaritem > a {
                > padding:0px 8px 0px 8px;
                > display:table-cell;
                > line-height:1.5em;
                > border:1px solid #d0d0d0;
                > }
                >
                > li.yuimenuitem > a {
                > padding:0px 8px 0px 8px;
                > border:none;
                > }
                >
                > li.yuimenuitem > a,
                > li.yuimenubaritem > a {
                > /*
                > "zoom:1" triggers "haslayout" in IE to ensure that
                the
                > mouseover and
                > mouseout events bubble to the parent LI in IE.
                > */
                > zoom:1;
                > color:#000;
                > text-decoration:none;
                > outline:none!important;
                > }
                >
                > /* Mouse hovering over MenuBarItem: Outset border */
                > li.yuimenubaritem > a:hover {
                > border-color: #f0f0f0 #909090 #909090 #f0f0f0;
                > color:#000000;
                > }
                >
                > /* Mouse hovering over MenuBar: white text on blue
                background */
                > li.yuimenuitem.mouseover {
                > border:none;
                > background-color: #000070;
                > color:#ffffff;
                > }
                >
                > /* //\\ Patch from Todd.
                > //\\ Did not make a difference */
                > div.yuimenu li.yuimenuitem img {
                > margin:0 -16px 0 10px;
                > border:0;
                > }
                >
                > /* This (less pecific) rule was already present. (The above
                one
                > shou;d be the standard)
                > Matches the sub menu indicator for a MenuItem instance
                > div.yuimenu li img {
                > margin:0 -16px 0 10px;
                > border:0;
                > }*/
                >
                > div.yuimenu li.hassubmenu,
                > div.yuimenu li.hashelptext {
                > text-align:right;
                > }
                >
                > div.yuimenu li.hassubmenu a.hassubmenu,
                > div.yuimenu li.hashelptext a.hashelptext {
                > float:left;
                > display:inline; /* Prevent margin doubling in IE */
                > text-align:left;
                > }
                >
                >
                > /* Matches focused and selected MenuItem instances */
                >
                > div.yuimenubar li.yuimenubaritem.selected > a {
                > background-color: #a0a0a0;
                > border-color: #909090 #f0f0f0 #f0f0f0 #909090!important;
                > color:#000000;
                > }
                >
                > div.yuimenu li.yuimenuitem.selected {
                > background-color: #000070;
                > color:#ffffff;
                > }
                >
                > div.yuimenu li.selected a.selected,
                > div.yuimenu li.selected em.selected,
                > div.yuimenubar li.selected a.selected {
                > color:#fff;
                > }
                >
                >
                > /* Matches disabled MenuItem instances */
                > div.yuimenu li.disabled,
                > div.yuimenubar li.disabled {
                > cursor:default;
                > }
                >
                > div.yuimenu li.disabled a.disabled,
                > div.yuimenu li.disabled em.disabled,
                > div.yuimenubar li.disabled a.disabled {
                > color:#b9b9b9;
                > cursor:default;
                > }
                >
                > div.yuimenubar li.yuimenubaritem {
                > float:left;
                > display:inline; /* Prevent margin doubling in IE */
                > margin:0;
                > }
                >
                > div.yuimenubar li.yuimenubaritem.first {
                > border-width:0;
                > }
                >
                > div.yuimenubar li.yuimenubaritem img {
                > margin:0 0 0 10px;
                > vertical-align:middle;
                > }
                > </style>
                > <link rel="stylesheet" type="text/css"
                href="css/screen.css" />
                > <link rel="stylesheet" type="text/css"
                href="css/local/tree.css" />
                > <style type="text/css">
                > #menuContainer {
                > float:left;
                > border:2px inset;
                > overflow:auto;
                > }
                >
                > #componentContainer {
                > float:left;
                > border:2px inset;
                > overflow:auto;
                > }
                >
                > .Component {
                > background-color:lightblue;
                > border-bottom:1px groove;
                > }
                > </style>
                > <script type="text/javascript">
                > // Starting with the given node, find the nearest
                containing
                > element
                > // with the specified tag name and optionally class name.
                > function getAncestorWithClass(node, tagName, className)
                > {
                > var lcTag = tagName.toLowerCase();
                > while (node != null)
                > {
                > if (node.tagName != null && node.tagName.toLowerCase
                ()
                > == lcTag)
                > {
                > if (typeof(className) != "undefined")
                > {
                > if (YAHOO.util.Dom.hasClass(node,
                className))
                > {
                > return node;
                > }
                > }
                > else
                > {
                > return node;
                > }
                > }
                > node = node.parentNode;
                > }
                >
                > return node;
                > }
                >
                > var tree;
                > function onWindowLoad()
                > {
                > tree = new DDTreeView("menuTree");
                > var menuBar = new YAHOO.widget.TextNode
                ({label:"Nigel's
                > Menu", href:"#"}, tree.getRoot(), false);
                > menuBar.canHaveChildren = true;
                > menuBar.data =
                > {className:"com.fcl.greenfield.entity.Menu", uuid:0};
                > menuBar.expand();
                > tree.draw();
                >
                > // Activate the components...
                > var c = new Component("Component:1", "menuTree")
                > c.copy = true;
                > c.data =
                > {className:"com.fcl.greenfield.entity.Component", uuid:1};
                > c = new Component("Component:2", "menuTree")
                > c.copy = true;
                > c.data =
                > {className:"com.fcl.greenfield.entity.Component", uuid:2};
                > c = new Component("Component:3", "menuTree")
                > c.copy = true;
                > c.data =
                > {className:"com.fcl.greenfield.entity.Component", uuid:3};
                > }
                >
                > DDTreeView = function(id)
                > {
                > this.init(id);
                > this.insertHighlight = document.createElement
                ("div");
                > this.insertHighlight.style.display = "none";
                > this.insertHighlight.style.position = "absolute";
                > this.insertHighlight.style.backgroundColor =
                > "activecaption";
                > this.insertHighlight.style.height = "2px";
                > this.insertHighlight.style.width = "45px";
                > document.body.appendChild(this.insertHighlight);
                > this.newNodeCount = 0;
                > }
                > DDTreeView.prototype = new YAHOO.widget.TreeView();
                > DDTreeView.prototype.superDraw =
                DDTreeView.prototype.draw;
                >
                > DDTreeView.prototype.draw = function()
                > {
                > // Call superclass's draw()
                > this.superDraw();
                >
                > // Make the tree droppable on.
                > new YAHOO.util.DDTarget
                (this.id, "menuTree").menuTree =
                > this;
                >
                > // Create ContextMenu
                > this.contextMenu = new
                > YAHOO.widget.ContextMenu("contextMenu", {trigger:this.id});
                > this.createMenuItem = new
                > YAHOO.widget.ContextMenuItem("New Submenu");
                >
                > this.createMenuItem.clickEvent.subscribe(this.createNewMenu, this,
                true);
                > this.contextMenu.addItem(this.createMenuItem);
                > this.deleteMenuItem = new
                > YAHOO.widget.ContextMenuItem("Delete");
                >
                > this.deleteMenuItem.clickEvent.subscribe(this.deleteMenu, this,
                true);
                > this.contextMenu.addItem(this.deleteMenuItem);
                >
                > // Add a "move" event handler to the context menu
                >
                > this.contextMenu.beforeShowEvent.subscribe(this.onMoveContextMenu,
                this,
                > true);
                > this.contextMenu.render(document.body);
                > }
                >
                > // Given a target DOM element, work up to find its label,
                > // extract the node index, and look it up in the tree.
                > DDTreeView.prototype.getTreeNode = function(target)
                > {
                > var result = getAncestorWithClass
                (target, "a", "ygtvlabel");
                > if (result && result.id)
                > {
                > result = YAHOO.widget.TreeView.getNode(this.id,
                > parseInt(/ygtvlabelel(\d+)/.exec(result.id)[1]));
                > }
                > return result;
                > }
                >
                > DDTreeView.prototype.onMoveContextMenu = function(e, o)
                > {
                > var target =
                > this.getTreeNode(this.contextMenu.contextEventTarget);
                > if (target)
                > {
                > // Disable creation if we clicked on a node that
                > can't have children
                > this.createMenuItem.cfg.setProperty("disabled",
                > !target.canHaveChildren);
                >
                > // Disable deletion if we clicked on the top
                level Menu.
                > this.deleteMenuItem.cfg.setProperty("disabled",
                > (target.parent == this.getRoot()));
                > }
                > else
                > {
                > this.contextMenu.cfg.applyConfig
                ({visible:false });
                > }
                > YAHOO.util.Event.preventDefault(e);
                > }
                >
                > // Called from the context menu in the scope of the
                MenuTree
                > DDTreeView.prototype.createNewMenu = function(e, o)
                > {
                > var target =
                > this.getTreeNode(this.contextMenu.contextEventTarget);
                > if (target)
                > {
                > target.collapse();
                > var submenu = new YAHOO.widget.TextNode
                ({label: "New
                > Menu " + (++this.newNodeCount), href:"#"}, target, false);
                > submenu.canHaveChildren = true;
                > submenu.data =
                > {className:"com.fcl.greenfield.entity.Menu"}
                > target.expand();
                > }
                > this.contextMenu.hide();
                > }
                >
                > // Called from the context menu in the scope of the
                MenuTree
                > DDTreeView.prototype.deleteMenu = function(e, o)
                > {
                > var target =
                > this.getTreeNode(this.contextMenu.contextEventTarget);
                > if (target)
                > {
                > target.parent.collapse();
                > this.removeNode(target);
                > target.parent.expand();
                > }
                > this.contextMenu.hide();
                > }
                >
                > // Returns the lowest target node at the event's
                coordinates
                > DDTreeView.prototype.getInsertionPoint = function(e)
                > {
                > this.insertHighlight.style.display = "none";
                > var p = new
                > YAHOO.util.Point(YAHOO.util.Event.getPageX
                (e),YAHOO.util.Event.getPageY(e));
                > var c = this.getRoot().children;
                > for (var i = 0; i < c.length; i++)
                > {
                > var result = this._getInsertionPoint(c[i], p);
                > if (result)
                > return result;
                > }
                > }
                >
                > /** Returns an object representing the target node
                position
                > at the event's coordinates.
                >
                > The object is {root:nodeToInsertInto
                > beforeNode|afterNode:reference node to
                > insert before or after}
                > */
                > DDTreeView.prototype._getInsertionPoint = function
                (node, p)
                > {
                > // The region occupied by the label element.
                > var labelRegion =
                > YAHOO.util.Region.getRegion(node.getLabelEl());
                >
                > if (node.canHaveChildren)
                > {
                > // The element containing child nodes.
                > var childElement = node.getChildrenEl();
                >
                > // Get the region occupied by the child nodes.
                > var childRegion =
                > YAHOO.util.Region.getRegion(childElement);
                >
                > // Get the region occupied by the whole root
                line.
                > Ensure it's as wide as the tree
                > var rootRegion =
                > YAHOO.util.Region.getRegion(childElement.previousSibling);
                > var treeRegion =
                > YAHOO.util.Region.getRegion(node.tree.getRoot().getEl());
                > rootRegion.left = treeRegion.left;
                > rootRegion.right = treeRegion.right;
                >
                > // If we're over the label, we're inserting
                either at
                > the top,
                > // or, if it's a collapsed node and we're below
                its
                > centre line,
                > // below it.
                > if (rootRegion.contains(p))
                > {
                > this.insertHighlight.style.top =
                > (labelRegion.bottom + 5) + "px";
                > this.insertHighlight.style.left =
                > (labelRegion.left + 17) + "px";
                > this.insertHighlight.style.display = "";
                >
                > // If the node is expanded, we're inserting
                > before its first child.
                > if (node.expanded)
                > return {root:node,
                beforeNode:node.children[0]};
                > else
                > {
                > // If the node is collapsed, then decide
                > whether to insert
                > // AFTER it, or INTO it.
                > if (!node.parent.isRoot())
                > {
                > // Hovering within 4 pixels of the
                bottom
                > - insert AFTER it
                > if (p.top > (rootRegion.bottom - 5))
                > {
                > this.insertHighlight.style.left
                =
                > labelRegion.left + "px";
                > return {root:node.parent,
                > afterNode:node};
                > }
                >
                > // Insert INTO it: Hide insertion
                point bar
                > this.insertHighlight.style.display
                = "none";
                > }
                >
                > // Unless it's a top level, in which
                case
                > INTO it.
                > return {root:node, beforeNode:null};
                > }
                > }
                >
                > else if (childRegion.contains(p))
                > {
                > // var result;
                > for (var i = 0; i < node.children.length;
                i++)
                > {
                > var result =
                > this._getInsertionPoint(node.children[i], p);
                > if (result)
                > return result;
                > }
                > }
                > }
                >
                > // We're hovering over a leaf node.
                > else
                > {
                > var e = YAHOO.util.Region.getRegion(node.getEl
                ());
                > if (e.contains(p))
                > {
                > this.insertHighlight.style.left =
                > labelRegion.left + "px";
                > this.insertHighlight.style.display = "";
                > if (p.isAbove(e))
                > {
                > prevNode = node.previousSibling;
                > if (!prevNode)
                > prevNode = node.parent;
                > this.insertHighlight.style.top =
                > (YAHOO.util.Region.getRegion(prevNode.getLabelEl()).bottom + 5)
                + "px";
                > return {root:node.parent,
                beforeNode:node};
                > }
                > else
                > {
                > this.insertHighlight.style.top =
                > (labelRegion.bottom + 5) + "px";
                > return {root:node.parent,
                afterNode:node};
                > }
                > }
                > }
                > this.insertHighlight.style.display = "none";
                > }
                >
                > DDTreeView.prototype.insertTextNodeBefore = function
                (label,
                > refNode, expanded)
                > {
                > var root = refNode.parent;
                > var node = new
                > YAHOO.widget.TextNode({label:this.getEl().innerHTML, href:"#"},
                root,
                > false);
                > this.removeNode(node);
                > root.insertBefore(node, refNode);
                > return node;
                > }
                >
                > DDTreeView.prototype.insertTextNodeAfter = function
                (label,
                > refNode, expanded)
                > {
                > var root = refNode.parent;
                > var node = new
                > YAHOO.widget.TextNode({label:this.getEl().innerHTML, href:"#"},
                root,
                > false);
                > this.removeNode(node);
                > root.insertAfter(node, refNode);
                > return node;
                > }
                >
                > /**
                > Extends DDProxy to allow copying of data.
                > */
                > var Component = function(id, sGroup)
                > {
                > this.copy = false;
                > this.init(id, sGroup);
                > this.initFrame();
                > this.selectedTarget = null;
                > this.isTarget = false;
                > };
                > Component.prototype = new YAHOO.util.DDProxy();
                >
                > Component.prototype.initFrame = function()
                > {
                > if (!Component.frameDiv)
                > {
                > if (!document || !document.body)
                > {
                > _this = this;
                > setTimeout(function()
                > {
                > Component.prototype.initFrame.call
                (_this)
                > }, 50);
                > return;
                > }
                > this.setDragElId("componentProxy");
                > Component.frameDiv = document.createElement
                ("div");
                > Component.frameDiv.id = "componentProxy";
                > var s = Component.frameDiv.style;
                > s.position = "absolute";
                > s.visibility = "hidden";
                > s.border = "none";
                > s.zIndex = 999;
                > document.body.appendChild(Component.frameDiv);
                > }
                > this.useAbsMath = true;
                > };
                >
                > Component.prototype.getDragEl = function()
                > {
                > return Component.frameDiv;
                > }
                >
                > Component.prototype.showFrame = function(iPageX, iPageY)
                > {
                > var el = this.getEl();
                > var dragEl = Component.frameDiv;
                > YAHOO.util.Dom.setStyle(dragEl, "opacity", 0.5);
                > dragEl.className = el.className;
                > dragEl.innerHTML = el.innerHTML;
                > var s = dragEl.style;
                > s.width = parseInt(el.offsetWidth, 10) + "px";
                > s.height = parseInt(el.offsetHeight, 10) + "px";
                > this.setDragElPos(iPageX, iPageY);
                > s.visibility = "";
                > document.body.style.cursor = "no-drop";
                > };
                >
                > Component.prototype.onDragEnter = function(e, id)
                > {
                > document.body.style.cursor = "copy";
                > };
                >
                > Component.prototype.onDragOut = function()
                > {
                > document.body.style.cursor = "no-drop";
                > if (this.selectedTarget)
                > this.selectedTarget.style.backgroundColor = "";
                > tree.insertHighlight.style.display = "none";
                > };
                >
                > Component.prototype.b4EndDrag = function()
                > {
                > this.getDragEl().style.visibility = "hidden";
                > if (this.selectedTarget)
                > this.selectedTarget.style.backgroundColor = "";
                > document.body.style.cursor = "";
                > };
                >
                > Component.prototype.onDragOver = function(e, id)
                > {
                > var menuTree = ((typeof id == "string") ?
                > YAHOO.util.DragDropMgr.getDDById(id) : id[0]).menuTree;
                > var insertionPoint = menuTree.getInsertionPoint(e);
                > if (insertionPoint)
                > {
                > var el = insertionPoint.root.getLabelEl();
                > if (this.selectedTarget &&
                (this.selectedTarget != el))
                > {
                > this.selectedTarget.style.backgroundColor
                = "";
                > }
                > this.selectedTarget = el;
                > this.selectedTarget.style.backgroundColor
                = "#ccddcc";
                > }
                > }
                >
                > Component.prototype.onDragDrop = function(e, id)
                > {
                > var menuTree = ((typeof id == "string") ?
                > YAHOO.util.DragDropMgr.getDDById(id) : id[0]).menuTree;
                > var insertionPoint = menuTree.getInsertionPoint(e);
                > if (insertionPoint)
                > {
                > if (insertionPoint.afterNode)
                > {
                > var n = new
                > YAHOO.widget.TextNode({label:this.getEl().innerHTML, href:"#"},
                > insertionPoint.root, false);
                > menuTree.removeNode(n);
                > insertionPoint.root.insertAfter(n,
                > insertionPoint.afterNode);
                > }
                > else
                > {
                > var n = new
                > YAHOO.widget.TextNode({label:this.getEl().innerHTML, href:"#"},
                > insertionPoint.root, false);
                > menuTree.removeNode(n);
                > insertionPoint.root.insertBefore(n,
                > insertionPoint.beforeNode);
                > }
                > n.data = this.data;
                > insertionPoint.root.refresh();
                >
                > // We've moved, not copied, so remove the
                original
                > node, and clear it's DragDrop
                > if (!this.copy)
                > {
                > var el = this.getDragEl();
                > el.parent.removeChild(el);
                > this.unreg();
                > }
                >
                > }
                > };
                >
                > // Don't remove the original node.
                > Component.prototype.endDrag = function()
                > {
                > tree.insertHighlight.style.display = "none";
                > };
                >
                > // Add a "load" handler for the window
                > YAHOO.util.Event.addListener(window, "load",
                onWindowLoad);
                >
                > </script>
                > </head>
                > <body>
                > <form id="mainForm">
                > <div id="menuContainer"
                > style="height:400px;width:300px;margin-right:10px;overflow:auto">
                > <a href="javascript:tree.expandAll()">Expand all</a>
                > <a href="javascript:tree.collapseAll()">Collapse
                all</a>
                > <div id="menuTree"></div>
                > </div>
                > <div id="componentContainer"
                style="height:400px;width:300px">
                > <div style="text-align:center">Components</div>
                > <div id="components">
                > <div class="Component"
                id="Component:1">Languages</div>
                > <div class="Component"
                id="Component:2">Countries</div>
                > <div class="Component" id="Component:3">Time
                zones</div>
                > </div>
                > </form>
                > </body>
                > </html>
                >
                >
                _____________________________________________________________________
                > This message has been checked for all known viruses. Virus scanning
                > powered by Messagelabs http://www.messagelabs.com For more
                information
                > e-mail : hostmaster@...
                >
              Your message has been successfully submitted and would be delivered to recipients shortly.