Ext.NET 3 Grid row drag/drop and text selection

  1. #1

    Ext.NET 3 Grid row drag/drop and text selection

    Hi,

    This is a follow up to this thread:

    http://forums.ext.net/showthread.php...text-selection

    The previous thread was for Ext.NET 1

    This follow up is to get the same thing working for Ext.NET 3

    The requirements are the same:
    • A grid that has text selection allowed (to copy/paste grid cell text)
    • Grid has checkbox row selection (this may work with other row selection methods but I have not tested them)
    • Drag/drop enabled on the grid
    • Allowing text selection on selected rows while drag/drop enabled (not possible by default)


    Ext JS 5.1 has many differences to Ext JS 3 which is what Ext.NET 1 is based on so the original solution I had of course won't work for the latest version.

    It is a bit simpler in this latest version, once I found where I had to make the change.

    In Ext JS 5.1, there is a DragZone component in Ext.view.DragZone

    Its default implementation for the getDragData method is this:

    getDragData: function (e) {
        var view = this.view,
            item = e.getTarget(view.getItemSelector())
    
        if (item) {
            return {
                copy: view.copy || (view.allowCopy && e.ctrlKey),
                event: e,
                view: view,
                ddel: this.ddel,
                item: item,
                records: view.getSelectionModel().getSelection(),
                fromPosition: Ext.fly(item).getXY()
            };
        }
    }
    The above is saying if you find the row corresponding to the item's row selected make that row draggable.

    In my case, while a row is selected, a user may not want to drag straight away, so wanting to select text, copy/paste etc is useful to preserve. The trade off is that I will only allow dragging if a particular part of the row is selected. In my case I have a row number column, so I will use that.

    So, we extend the above as follows:

    Ext.define('overrides.view.DragZone', {
        override: 'Ext.view.DragZone',
    
        getDragData: function (e) {
            var view = this.view,
                item = e.getTarget(view.getItemSelector()),
                target = e.getTarget();
    
            // ADDED: Allow text selection to continue if not dragging anything other than the row numberer column
            if (target && target.className.indexOf('x-grid-cell-inner-row-numberer') == -1)
                return false;
    
            if (item) {
                return {
                    copy: view.copy || (view.allowCopy && e.ctrlKey),
                    event: e,
                    view: view,
                    ddel: this.ddel,
                    item: item,
                    records: view.getSelectionModel().getSelection(),
                    fromPosition: Ext.fly(item).getXY()
                };
            }
        }
    });
    All I've done is add a target variable, and check if the target DOM element has a class name corresponding to the row numberer (i.e. was it the row numberer cell for that row that was clicked to start the drag process). If not, then return false, and let other configured behaviour continue, else continue with the drag process.

    So 3 things I've done to put it together:
    1. Applied the override for [var]getDragData]/var]
    2. Configured the grid's View to allow text selection (using EnableTextSelection="true")
    3. (Optional) To make it a bit easier to know that a row can be dragged, inside the row numberer cell, I've added a bit of CSS to insert a drag handle (background image) when that row is selected.


    Here is an example putting it together:

    <%@ Page Language="C#" %>
    
    <script runat="server">
        private object[] TestData
        {
            get
            {
                DateTime now = DateTime.Now;
    
                return new object[]
                {
                    new object[] { "3m Co", 71.72, 0.02, 0.03, now },
                    new object[] { "Alcoa Inc", 29.01, 0.42, 1.47, now },
                    new object[] { "Altria Group Inc", 83.81, 0.28, 0.34, now },
                    new object[] { "American Express Company", 52.55, 0.01, 0.02, now },
                    new object[] { "American International Group, Inc.", 64.13, 0.31, 0.49, now },
                    new object[] { "AT&T Inc.", 31.61, -0.48, -1.54, now },
                    new object[] { "Boeing Co.", 75.43, 0.53, 0.71, now }
                };
            }
        }
        
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!X.IsAjaxRequest)
            {
                Store1.DataSource = TestData;
                Store1.DataBind(); 
            }
        }
    </script>
    
    <!DOCTYPE html>
    <html>
    <head runat="server">
        <title>Drag and Drop GridPanel Example</title>
    
        <style>
            .x-grid-item-selected .x-grid-cell-row-numberer {
                background: no-repeat left center;
                background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOAQMAAAAlhr+SAAAABlBMVEX///+Tk5OZ/c7wAAAAAXRSTlMAQObYZgAAABtJREFUeF59xrENAAAAgjAP5v9ZjbsNAwramTFNygNhn4U+IQAAAABJRU5ErkJggg==') /*i/icons/drag-indicator.png*/;
                cursor: move;
            }
        </style>
    
        <ext:ResourcePlaceHolder Mode="ScriptFiles" />
    
        <script>
            Ext.define('overrides.view.DragZone', {
                override: 'Ext.view.DragZone',
    
                getDragData: function (e) {
                    var view = this.view,
                        item = e.getTarget(view.getItemSelector()),
                        target = e.getTarget();
    
                    // this if block added to allow text selection to continue if not dragging anything other than the checkbox column
                    if (target && target.className.indexOf('x-grid-cell-inner-row-numberer') == -1)
                        return false;
    
                    if (item) {
                        return {
                            copy: view.copy || (view.allowCopy && e.ctrlKey),
                            event: e,
                            view: view,
                            ddel: this.ddel,
                            item: item,
                            records: view.getSelectionModel().getSelection(),
                            fromPosition: Ext.fly(item).getXY()
                        };
                    }
                }
            });
        </script>
    </head>
    <body>
        <ext:ResourceManager runat="server" />
            
        <ext:GridPanel 
            ID="GridPanel1"
            runat="server" 
            Title="Array Grid" 
            EnableDragDrop="true"
            Width="600" 
            Height="350">
            <Store>
                <ext:Store ID="Store1" runat="server">
                    <Model>
                        <ext:Model runat="server">
                            <Fields>
                                <ext:ModelField Name="company" />
                                <ext:ModelField Name="price" Type="Float" />
                                <ext:ModelField Name="change" Type="Float" />
                                <ext:ModelField Name="pctChange" Type="Float" />
                                <ext:ModelField Name="lastChange" Type="Date" DateFormat="M/d hh:mmtt" />
                            </Fields>
                        </ext:Model>
                    </Model>
                </ext:Store>
            </Store>
            <ColumnModel>
                <Columns>
                    <ext:RowNumbererColumn />
                    <ext:Column Text="Company" DataIndex="company" Flex="1" />
                    <ext:Column Text="Price" DataIndex="price">                  
                        <Renderer Format="UsMoney" />
                    </ext:Column>
                    <ext:Column Text="Change" DataIndex="change" />
                    <ext:Column Text="Change" DataIndex="pctChange" />
                    <ext:DateColumn Text="Last Updated" DataIndex="lastChange" />
                </Columns>            
            </ColumnModel>       
            <SelectionModel>
                <ext:CheckboxSelectionModel CheckOnly="true" InjectCheckbox="1" />
            </SelectionModel>
            <View>
                <ext:GridView EnableTextSelection="true">
                    <Plugins>
                        <ext:GridDragDrop DDGroup="GridDDGroup" />
                    </Plugins>
                </ext:GridView>
            </View>
        </ext:GridPanel>
    </body>
    </html>
    With the example above
    • You can select rows, and any selected rows will show a row handle in the row numberer column
    • You can select text from cells of any rows, including any selected (checked) rows [previously you could only select text for non-selected rows]
    • If you initiate a drag from the row numberer column, you will be able to drag that row (for this example you can re-order the rows on the grid)
    • If you attempt to initiate a drag from another cell of a selected row, then you won't be able to (it will select text in most cases). This is the trade-off of this solution.


    I hope that is useful. I've tested this in latest Firefox, latest Chrome and latest IE11. I've not tested IE10 or below though I think it should work.

    Also, if this can be done in a more simpler way, please do let me know!
    Last edited by anup; Jan 19, 2015 at 1:21 PM.

Similar Threads

  1. [CLOSED] Grid row drag/drop and text selection
    By anup in forum 1.x Legacy Premium Help
    Replies: 5
    Last Post: Jan 19, 2015, 1:22 PM
  2. Replies: 4
    Last Post: Jul 19, 2013, 1:16 AM
  3. [CLOSED] Ext.Net grid drag & drop on header
    By adrianot in forum 2.x Legacy Premium Help
    Replies: 4
    Last Post: Apr 23, 2013, 12:09 PM
  4. [CLOSED] Grid Drag and Drop with RowBody
    By blueworld in forum 2.x Legacy Premium Help
    Replies: 4
    Last Post: Apr 03, 2013, 9:16 AM
  5. selection problem if drag drop is enabled
    By [WP]joju in forum 1.x Help
    Replies: 0
    Last Post: Feb 19, 2010, 12:38 AM

Posting Permissions