Class: cWebDragDropHelper

Properties  Events  Methods    Index of Classes

Adds drag and drop fuctionality to web controls

Hierarchy

cObject
---cWebObject
------cWebDragDropHelper
---------cWebDragDropFileHelper

Library: Web Application Class Library

Package: cWebDragDropHelper.pkg

Description

Adds drag and drop fuctionality to web controls.

Drag Actions

The following classes support elements being dragged for specific actions using the following constants:

cWebList: C_WebDragListRow
cWebTreeView: C_WebDragTreeviewFolder, C_WebDragTreeviewItem
cWebTagsForm: C_WebDragTagsFormTag

Attempting to add an unsupported drag action to a control will result in an Error.

Drop Actions


Every visual web control, including containers like cWebPanel or cWebGroup, supports the C_WebDropOnControl action. This allows the entire control to function as a drop zone.

The following classes support elements being dropped onto for specific actions using the following constants:

All web controls: C_WebDropOnControl
cWebList: C_WebDropListRow
cWebTreeView: C_WebDropTreeviewRoot, C_WebDropTreeviewFolder, C_WebDropTreeviewItem
cWebTagsForm: C_WebDropTagsFormInput


General Use Outline


1. Add a cWebDragDropHelper object to your view.

Adding a cWebDragDropHelper object to your view unlocks the drag and drop functionality. After creating the cWebDragDropHelper object, configure the allowed actions.

2. Design your drag and drop paths by adding Drag Sources and Drop Targets

Next set up your drag and drop paths, as well as, configure what actions you would like to support.

Adding Drag Sources is done using RegisterDragSource. Adding Drop Targets is done using RegisterDropTarget.

To support multiple drag actions on the same control, such as being able to drag both folders and items in a treeview, you would call RegisterDragSource again on the same control passing different actions. The same applies to supporting multiple drop actions.

Note that each Drag Source in a specific helper can drop on each Drop Target added inside. Controls can also function as both a Drag Source and a Drop Target at the same time, allowing for omnidirectional drag and drop interaction.

Sample

In the example below, we allow drag actions from 5 different controls. Items dragged from these controls can be dropped onto 6 controls. Some of these controls are registered as both a Drag Source and a Drop Target.

Object oDragDropHelper is a cWebDragDropHelper
        Send RegisterDragSource oAllCustomers C_WebDragListRow
        
        Send RegisterDragSource oNiceCustomers C_WebDragListRow
        Send RegisterDragSource oBadCustomers C_WebDragListRow
        Send RegisterDragSource oImportantCustomers C_WebDragTagsFormTag
        Send RegisterDragSource oSortedCustomers C_WebDragTreeviewItem
        
        Send RegisterDropTarget oNiceCustomers C_WebDropListRow
        Send RegisterDropTarget oBadCustomers C_WebDropListRow
        Send RegisterDropTarget oImportantCustomers C_WebDropTagsFormInput
        Send RegisterDropTarget oSortedCustomers C_WebDropTreeviewFolder
        
        Send RegisterDropTarget oWebFormDrop C_WebDropOnControl
        Send RegisterDropTarget oWebGroupDrop C_WebDropOnControl


3. Add your business logic to be executed when a drop happens by implementing the OnDrop event

When dropping a draggable element on a valid Drop Target, a call is sent to the server with info of the dragged data and the drop position. This is passed to the OnDrop event, where business logic can be executed to interact with this data.

Sample

The sample code below moves a customer from the source control to the target control.

Procedure OnDrop Handle hoDragSource Handle hoDropTarget WebDropPosition eDropPosition
    RowID riCustomer
    
    //  Determine which customer is being dragged
    Get CustomerFromSource hoDragSource to riCustomer
    If (not(IsNullRowID(riCustomer))) Begin
        
        //  Remove from the source (except for the oAllCustomers list)
        If (hoDragSource <> oAllCustomers) Begin
            Send RemoveCustomerFromSource hoDragSource riCustomer
        End
        
        //  Add to the target
        Send AddCustomerToTarget riCustomer hoDropTarget eDropPosition
    End
End_Procedure


3a. Getting drag and drop data

Both drag and drop data are not passed directly into the OnDrop event. They are set on both the hoDragSource and hoDropTarget at an earlier stage and can be retrieved by using either DragData or DropData. The return value is inherently a Variant, but will return a specific struct based on the control it's being requested from.

Sample

The example code below illustrates how to deal with getting the Drag and Drop data from the respective controls, as well as various ways of interacting with the data per individual control.

Function CustomerFromSource Handle hoDropSource Returns RowID
    If (IsObjectOfClass(hoDropSource, RefClass(cWebTagsForm))) Begin
        tWebTagsFormDragData tagsDragData
        Get DragData of hoDropSource to tagsDragData
        
        Clear Customer
        Move tagsDragData.data to Customer.Name
        Find GE Customer.Name
        If (Found and Trim(Customer.Name) = Trim(tagsDragData.data)) Begin
            Function_Return (GetRowID(Customer.File_Number))
        End
    End
    
    If (IsObjectOfClass(hoDropSource, RefClass(cWebList))) Begin
        tWebListDragData listDragData
        Get DragData of hoDropSource to listDragData
        
        Function_Return (DeserializeRowID(listDragData.data.sRowId))
    End
    
    If (IsObjectOfClass(hoDropSource, RefClass(cWebTreeView))) Begin
        tWebTreeViewDragData treeDragData
        Get DragData of hoDropSource to treeDragData
        
        Function_Return (DeserializeRowID(treeDragData.data.sId))
    End
    
    Function_Return (NullRowID())
End_Function

//  
//  Adds an item onto the Drop Target based on the provided RowId. Switches between the different target types.
//
Procedure AddCustomerToTarget RowID riCustomer Handle hoDropTarget WebDropPosition eDropPosition
    Boolean bFound
    
    Move (FindByRowID(RefTable(Customer), riCustomer)) to bFound
    
    If (IsObjectOfClass(hoDropTarget, RefClass(cWebTagsForm))) Begin
        //  We don't use the drop data, but just for fun we load it
        tWebTagsFormDropData tagsDropData
        Get DropData of hoDropTarget to tagsDropData
        
        Send AddTag of hoDropTarget (Customer.Name)
    End
    
    If (IsObjectOfClass(hoDropTarget, RefClass(cWebForm))) Begin
        WebSet psValue of hoDropTarget to (Trim(Customer.Name))
    End
    If (IsObjectOfClass(hoDropTarget, RefClass(cWebGroup))) Begin
        String sMsg
        Move ('Dropped customer: "' + Trim(Customer.Name) + '" on WebGroup') to sMsg
        Send ShowInfoBox sMsg
    End
    
    If (IsObjectOfClass(hoDropTarget, RefClass(cWebList))) Begin
        tWebListDropData listDropData
        Get DropData of hoDropTarget to listDropData
        
        //  Check if customer isn't already in the list
        RowID[] riRecordsShown
        WebGet prRecordsShown of hoDropTarget to riRecordsShown
        If (SearchArray(riCustomer, riRecordsShown) = -1) Begin
            Move riCustomer to riRecordsShown[SizeOfArray(riRecordsShown)]
            WebSet prRecordsShown of hoDropTarget to riRecordsShown
           
            //   Now add it to the list
            tWebRow tListRow
            Get LoadGridRow of hoDropTarget to tListRow
            
            If (eDropPosition = C_WebDropPosBefore or eDropPosition = C_WebDropPosOn) Begin
                Send DataSetInsertRowBefore of hoDropTarget listDropData.data.sRowId tListRow
            End
            Else If (eDropPosition = C_WebDropPosAfter) Begin
                Send DataSetInsertRowAfter of hoDropTarget listDropData.data.sRowId tListRow
            End
            Else Begin
                Send DataSetAppendRow of hoDropTarget tListRow
            End
        End
    End
    
    If (IsObjectOfClass(hoDropTarget, RefClass(cWebTreeView))) Begin
        //  Figure out drop data
        tWebTreeViewDropData treeDropData
        Get DropData of hoDropTarget to treeDropData
        
        //  Remove to be sure we don't get duplicates
        Send RemoveNode of hoDropTarget (SerializeRowID(riCustomer))
        
        //  Create new node
        tWebTreeItem newItem
        
        Move (SerializeRowID(riCustomer)) to newItem.sId
        Move Customer.Name to newItem.sName
        Move Customer.City to newItem.sAltText
        Move False to newItem.bFolder
        Move treeDropData.data.sId to newItem.sParentId //  Make it a child of what we dropped it on
        
        Send InsertNode of hoDropTarget newItem
    End
End_Procedure

//  
//  Removes an item from the Drag Source. Switches between the different source types.
//
Procedure RemoveCustomerFromSource Handle hoDragSource RowID riCustomer
    If (IsObjectOfClass(hoDragSource, RefClass(cWebTagsForm))) Begin
        Boolean bFound
        
        Move (FindByRowID(RefTable(Customer), riCustomer)) to bFound
        
        If (bFound) Begin
            Send RemoveTag of hoDragSource (Customer.Name)
        End
    End
    
    If (IsObjectOfClass(hoDragSource, RefClass(cWebList))) Begin
        RowID[] riRecordsShown
        Integer iIndex
        
        //  Update the extra list of shown customers we keep for both weblists.
        WebGet prRecordsShown of hoDragSource to riRecordsShown
        Move (SearchArray(riCustomer, riRecordsShown)) to iIndex
        If (iIndex <> -1) Begin
            Move (RemoveFromArray(riRecordsShown, iIndex)) to riRecordsShown
            WebSet prRecordsShown of hoDragSource to riRecordsShown
            Send DataSetRemoveRow of hoDragSource (SerializeRowID(riCustomer))
        End
    End
    
    If (IsObjectOfClass(hoDragSource, RefClass(cWebTreeView))) Begin
        Send RemoveNode of hoDragSource (SerializeRowID(riCustomer))
    End
End_Procedure