Applying Drag-and-Drop to XTree

Overview
This is a simple application with two simple trees with 2 nodes on each one. To simplify the code, this example is not using any persistence or style.

We will focus only on the most important pieces that are the use of the xTree API’s and the use of the Drag and Drop pre-defined functions. Here is the complete code:

<%@ taglib uri="http://www.jway.com/xui" prefix="xui"  %>
<%@ page contentType="text/html; charset=UTF-8" %>
<xui:view validation="true">
    <xframe>
        <properties>
            <title>Drag and drop of xtree</title>
            <xscript language="javascript">
            
                 function dragTreeEnter (dragEvent) { }
                 
                 function dragTreeExit ()     {     }
                 
                 function initDragTreeSource(dragEvent)    {        
                    dragEvent.startDrag("hand");
                }
                
                 function dragTreeOver ()     {     }
                 
                 function dragTreeDrop (dragEvent)     {
                    //var _transferObject = dragEvent.getTransferObject();
                    var _target = dragEvent.getTarget();
                    var _source = dragEvent.getSource();
    
                    //put the old selected node to new position
                    if (_source.getType() == "XTree")    {
                            /*
                                This is to make sure the Source and Target nodes exist.
                            */
                            if( (_target==null) || (_source==null)
                                || (_target.currentHighlightedNode==null)
                                || (_source.currentSelectedNode==null)
                            )    {
                                return;
                            }
                            
                            if(_source.currentSelectedNode.id=="DontDragMe")
                            {
                                return;
                            }
                            
                            if(_target.currentHighlightedNode.id=="DontDragMe")
                            {
                                return;
                            }
                            
                            _source.currentSelectedNode.move(_target.currentHighlightedNode);    
                    }
                 }
                 
            </xscript>
        </properties>
            <xcontentpane style="padding:20px;">
            <layoutmanager type="grid-layout" grid-layout-cols="1" grid-layout-rows="1" cell-style="valign:top; padding:15px;"/>
            <xpanel>
            <xtree id="tree1" 
                drag-enter="dragTreeEnter"
                drag-over="dragTreeOver"
                drag-exit="dragTreeExit"
                drag-drop="dragTreeDrop"    
                drag-begin="initDragTreeSource">
                
                <treenode expanded="true" text="First Tree" id="DontDragMe">
                    <treenode text="Node 1.1"/>
                    <treenode text="Node 1.2"/>
                    <treenode text="Node 1.3"/>
                    <treenode text="Node 1.4"/>
                </treenode>
            </xtree>
            </xpanel>
            
            <xpanel>
            <xtree id="tree2"
                drag-enter="dragTreeEnter"
                drag-over="dragTreeOver"
                drag-exit="dragTreeExit"
                drag-drop="dragTreeDrop"    
                drag-begin="initDragTreeSource">

                <treenode expanded="true" text="Second Tree">
                    <treenode text="Node 2.1"/>
                    <treenode text="Node 2.2"/>
                    <treenode text="Node 2.3"/>
                    <treenode expanded="true" text="Node 2.4">
                        <treenode text="Node 2.4.1"/>
                        <treenode text="Node 2.4.2"/>
                    </treenode>
                    <treenode text="Node 2.5"/>
                    <treenode text="Node 2.6"/>
                    <treenode text="Node 2.7"/>
                </treenode>
            </xtree>            
            </xpanel>
        </xcontentpane>
    </xframe>
</xui:view>

 

Creating the application

1. Create a new JSP page. Copy and paste the following into this new file.

<xui:view validation="true">
<xframe>
<properties>
<title>Drag and drop of xtree</title>
</properties>
<xcontentpane style="padding:20px;">

</xcontentpane>
</xframe>
</xui:view>


2. Inside the <xcontentpane> tag, insert an xtree as follows:

<xcontentpane style="padding:20px;">
   <xpanel>
	   <xtree id="tree1">
		  <treenode expanded="true" text="First Tree" id="DontDragMe">
			  <treenode text="Node 1.1"/>
			  <treenode text="Node 1.2"/>
			  <treenode text="Node 1.3"/>
			  <treenode text="Node 1.4"/>
		  </treenode>
		</xtree>
    <xpanel>
</xcontentpane>

3. In the <xtree element, add the following attributes and values to give it the ability to drag-and-drop:

<xcontentpane style="padding:20px;">
   <xpanel>
	   <xtree id="tree1"
             drag-enter="dragTreeEnter"
drag-over="dragTreeOver"
drag-exit="dragTreeExit"
drag-drop="dragTreeDrop"
drag-begin="initDragTreeSource"
> <treenode expanded="true" text="First Tree" id="DontDragMe"> <treenode text="Node 1.1"/> <treenode text="Node 1.2"/> <treenode text="Node 1.3"/> <treenode text="Node 1.4"/> </treenode> </xtree> <xpanel>
</xcontentpane>

4. Let’s add a second tree with the Drag and Drop. Notice that we are using the same functions (dragTreeXXXX) for both trees, this is just for this example purposes, but you can define different functions for different trees. Notice also that we are now using a layout manager (grid layout) to format our screen.

<xcontentpane style="padding:20px;">
<layoutmanager type="grid-layout" grid-layout-cols="1" grid-layout-rows="1" cell-style="valign:top; padding:15px;"/>
	<xpanel>
		<xtree id="tree1"
			drag-enter="dragTreeEnter"
			drag-over="dragTreeOver"
			drag-exit="dragTreeExit"
			drag-drop="dragTreeDrop"	
			drag-begin="initDragTreeSource">
			<treenode expanded="true" text="First Tree" id="DontDragMe">
				<treenode text="Node 1.1"/>
				<treenode text="Node 1.2"/>
				<treenode text="Node 1.3"/>
				<treenode text="Node 1.4"/>
			</treenode>
		</xtree>
	</xpanel>

	<xpanel>
		<xtree id="tree2"
			drag-enter="dragTreeEnter"
			drag-over="dragTreeOver"
			drag-exit="dragTreeExit"
			drag-drop="dragTreeDrop"	
			drag-begin="initDragTreeSource">
			<treenode expanded="true" text="Second Tree">
				<treenode text="Node 2.1"/>
				<treenode text="Node 2.2"/>
				<treenode text="Node 2.3"/>
					<treenode expanded="true" text="Node 2.4">
						<treenode text="Node 2.4.1"/>
						<treenode text="Node 2.4.2"/>
					</treenode>
				<treenode text="Node 2.5"/>
				<treenode text="Node 2.6"/>
				<treenode text="Node 2.7"/>
			</treenode>
		</xtree> 
	</xpanel>
</xcontentpane> 

Defining the Drag and Drop Functions

To complete the functionality, the JavaScript drag functions must be defined. Refer to the drag and drop introduction for additional information on the specifics of each of the functions given below. In addition, the XUI JavaScript API can be used as reference for the xtabbedpane functions mentioned here. Refer to the comments in the code for a brief explanation of the particular function.

1. Each of the drag and drop functions called in the previous section must now be given the proper action. Create these functions within the <xscript> tags in the XUI source page. On this example we don’t need to implement anything for drag-enter, drag-exit, drag-over, but since we defined then on the attributes, we will put them as “empty” functions.

On drag-init, we set the dragEvent API to show a hand at the moment we drag the object.

<xcontentpane>
<xscript>

function dragTreeEnter (dragEvent) { }
function dragTreeExit () { }
function dragTreeOver () { }

function initDragTreeSource(dragEvent) { 
	dragEvent.startDrag("hand");
}
function dragTreeDrop (dragEvent)	 
{

/* On drag-drop, we get the source and target objects. */

var _target = dragEvent.getTarget();
var _source = dragEvent.getSource();

if (_source.getType() == "XTree") {

/*

Then our first step is to verify that we drag-and-drop from one tree node to another tree node, otherwise we will not perform anything.


This is to make sure the Source and Target nodes exist.
*/
if( (_target==null) || (_source==null)
|| (_target.currentHighlightedNode==null)
|| (_source.currentSelectedNode==null)
) {
return;
}

/* After we verified that we have the source and target tree nodes, using the xTree’s APIs, we move the node. */

_source.currentSelectedNode.move(_target.currentHighlightedNode);
}
}

</xscript>
</xcontentpane>


In this function, we set and create the Transfer Object. Creating the transfer object is done in: dragEvent.setTransferObject(transferObject). Also, in this case, we are using the “hand” icon as the default during drag events.

function dragXTPExit ()
{
	//  only used if there is a specific action necessary when the source item is dragged
//  outside of it's source component.  Because there is no dragging outside of a single
//  tabbedpane, this function is left empty
	 }
			
function dragXTPEnter (dragEvent)
 {
		// retrieves the target component that was entered

var _transferObject = dragEvent.getSource();
	 }
					 
		 
function dragXTPOver ()
	 {
		// in case of the hover over the target.  Intentionally left blank
	 }
 function dragXTPDrop (dragEvent)
	{
		// completion and transfer of the data to the target
		// initially set the source and target values, then move the tab (node)
		
		var _transferObject = dragEvent.getTransferObject();
		var _target = dragEvent.getTarget();
		var _source = dragEvent.getSource();

		//remove the old selected node				
		// put the old selected node to new position (moveTab())
		// Please refer to the XUI JavaScript APIs for more information.

		if (_source.getType() == "XTabbedPane")
		{
			_target.moveTab(_source.selectedTab, _source.id, _target.highlightedIndex);
		}
	}

In the dragXTPDrop() function, the first declaration is defining the Target and Source objects by invoking the getTarget() and getSource() methods, respectively. Please refer to the drag and drop overview section for more detailed information on these methods.

The final condition in dragXTPDrop() looks to see if the source object is a tabbedpane. That condition means that the source and target are both within the xtabbedpane and the moveTab() is then executed. Since other XUI components are capable of drag and drop (xtree and xtable), this becomes more important when other XUI components are dragged into the xtabbedpane.

Setting UI-Persistence

1. Finally, one important factor in creating maintaining state in the xtabbedpane is to set the “ui-persistence” attribute to “true” in the <xtabbedpane> tag.

<xtabbedpane tab-position="top" 
height="200px"
width="275px"
drag-enter="dragXTPEnter"
drag-over="dragXTPOver"
drag-exit="dragXTPExit"
drag-drop="dragXTPDrop"
drag-begin="initDragXTPSource"
ui-persistence="true">

By enabling persistence, the xtabbedpane is capable of two important features. First, as in a standard xtabbedpane persistence, the selected tab will be maintained even after the session is complete. Now, with the added feature of draggable tabs, persistence will also maintain the relative position of the tabs after completion of the session. It is important to note this function uses browser-based cookies which follow the typical cookie limitations.

For most applications, the code above will work well for any xtabbedpane that requires drag and drop capability. Simply cutting and pasting the code will give the desired functionality.

Next: Applying Drag-and-Drop to XTabbedpane
Back to: Application Guide

 

 


COPYRIGHT © 1997–2006 JWAY GROUP, Inc.
All Rights Reserved. XUI is a registered trademark of JWAY GROUP, Inc.

All other designated trademarks and brands are properties of their respective owners.