1. #1
    Sencha User
    Join Date
    May 2013
    Posts
    10
    Vote Rating
    0
    Revingbell is on a distinguished road

      0  

    Default Unanswered: Drag & drop in a viewport, between regions, goal: visual studio behavior.

    Unanswered: Drag & drop in a viewport, between regions, goal: visual studio behavior.


    Hello there,

    Here's my issue, i'm trying to make it that when i create my webpage with a viewport in it, i can easily drag and drop sub-items between regions: as an example i'd like to be able to have a child of the west panel region be draggable and then droppable inside the east panel region.

    The aim of this is eventually to have my web application work a little like visual studio with it's widgets, where you can drag & drop them anywhere and they adjust to the area they are dropped in.

    But that's the ideal behavior, for now i'm just trying to drag & drop panels between the "panels" of the different regions, and have hem reorder automatically like in the Tree example "Drag and Drop Reordering".

    So as for right now, I've already tried it 2 ways:
    • First I tried to use the drag and drop tutorial I found in the documentation guides. I'm currently having the following issues with it:
    1. I can't seem to have them reorder properly. Either I don't authorize dropping in parent node, and then I can't move anything around in the parent panel, the children just go back to their original position. Either I authorize it, but when I move an item for an inch without placing it under another inside the same parent, it reorders nonetheless by placing it under the others.
    2. When i drag an item somewhere else in the web page, it just goes under as if it's extending it's own parent until i drop it. Here is a screenshot to help you understand better: (see "children_goin_under")
    3. I can't seem to go left or top when i'm dragging a child item. What I mean by that is that my cursor will go there, but the child item just says stuck into his initial position. For this issue i found this thread online, but i haven't had the chance to try it yet: http://www.sencha.com/forum/showthre...tem-up-or-left
    4. Now to my main problem: when the events collapse and expand are triggered, all my children items go back to their initial position, inside their initial parent (except when for example I collapse west with my children dropped inside the eastern panel, then it will wait until west is expanded again to reinitialize their positions) . I don't really know why (and that's kinda the reason why i'm posting this thread), but it seems that the stores of all parent panels aren't updating, the drop target panel to include the new child item when i drop it in, and the former parent to remove the child.
    Here's the code for that application:
    Code:
    <script type="text/javascript">
        Ext.require(['*']);
    
    
        Ext.onReady(function () {
    
    
            Ext.QuickTips.init();
    
    
            Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));
    
    
            Ext.create('Ext.Component', {
                renderTo: "testViewPort",
                height: 32,
                collasible: true,
                border: 5,
                draggable: true,
            })
    
    
            var viewport = Ext.create('Ext.Viewport', {
                id: 'viewport',
                layout: 'border',
                items: [
                    Ext.create('Ext.Component', {
                        region: 'north',
                        height: 32,
                        autoEl: {
                            tag: 'div',
                            html: '<p>north</p>'
                        }
                    }), {
                        region: 'south',
                        contentEl: 'south',
                        split: true,
                        height: 100,
                        minSize: 100,
                        maxSize: 200,
                        collapsible: true,
                        collapsed: true,
                        title: 'South',
                        margins: '0 0 0 0'
                    }, {
                        region: 'east',
                        id: 'east-panel',
                        title: 'East Side',
                        collapsible: true,
                        split: true,
                        width: 225,
                        minSize: 175,
                        maxSize: 400,
                        height: 200,
                        margins: '0 5 0 0',
                    }, {
                        region: 'west',
                        id: 'west-panel',
                        title: 'West',
                        split: true,
                        width: 200,
                        minWidth: 175,
                        maxWidth: 400,
                        collapsible: true,
                        margins: '0 0 0 5',
                        items: [{
                            title: 'West 1',
                            region: 'north',
                            cls: 'widget',
                            minWidth: 80,
                            height: 100,
                            html: 'First West Panel to be dragged',
                        }, {
                            title: 'West 2',
                            cls: 'widget',
                            region: 'north',
                            minWidth: 80,
                            height: 100,
                            html: 'Second West Panel to be dragged',
                        }],
                    }, {
                        region: 'center',
                        id: 'center-panel',
                        collapsible: true,
                        draggable: true,
                        resizable: true,
                    },
                ]
            });
    
    
            var overrides = {
    
    
                b4StartDrag: function () {
                    if (!this.el) {
                        this.el = Ext.get(this.getEl());
                    }
    
    
                    this.originalXY = this.el.getXY();
                },
    
    
                onInvalidDrop: function () {
                    this.invalidDrop = true;
                },
    
    
                endDrag: function () {
                    if (this.invalidDrop === true) {
    
    
                        this.el.removeCls('dropOK');
    
    
                        var animCfgObj = {
                            easing: 'elasticOut',
                            duration: 1,
                            scope: this,
                            callback: function () {
                                this.el.dom.style.position = '';
                            }
                        };
    
    
                        this.el.moveTo(this.originalXY[0], this.originalXY[1], animCfgObj);
                        delete this.invalidDrop;
                    }
    
    
                },
    
    
                onDragDrop: function (evtObj, targetElId) {
    
    
                    var dropEl = Ext.get(targetElId);
                    console.log(targetElId);
    
    
                    if (this.el.dom.parentNode.id != targetElId || this.el.dom.parentNode.id == targetElId) {
    
    
                        dropEl.appendChild(this.el);
    
    
                        this.onDragOut(evtObj, targetElId);
    
    
                        this.el.dom.style.position = '';
                        this.el.dom.style.top = '';
                        this.el.dom.style.left = '';
                    }
                    else {
                        this.onInvalidDrop();
                    }
                },
    
    
                onDragEnter: function (evtObj, targetElId) {
    
    
                    if (targetElId != this.el.dom.parentNode.id) {
                        console.log("elAddClass",this.el);
                        this.el.addCls('dropOK');
                    }
                    else {
                        this.onDragOut();
                    }
                },
    
    
                onDragOut: function (evtObj, targetElId) {
                    this.el.removeCls('dropOK');
                }
            };
    
    
            var widgetElements = Ext.get('ext-gen1018').select('div.widget');
            Ext.each(widgetElements.elements, function (el) {
                var dd = new Ext.dd.DD(el, 'widgetGroup', {
                    isTarget: false
                });
    
    
                Ext.apply(dd, overrides);
            });
    
    
            var westPanelDDTarget = new Ext.dd.DDTarget('west-panel-body', 'widgetGroup');
            var eastPanelDDTarget = new Ext.dd.DDTarget('east-panel-body', 'widgetGroup');
            var allPanelDDTarget = new Ext.dd.DDTarget('center-panel-body', 'widgetGroup');
    
    
        });
    </script>
    • The second way I've been trying to do this is by using DragZones and DropZones, and i'm having the following issues:
    1. I'm having the exact same issue as #4 above.
    2. I've tried solving this issue by using either
      Code:
      delete thenodetodelete
      which does nothing at all (it does the exact same thing if I put it or not), or by trying the remove() function:
      Code:
      thenodetodelete.remove()
      but it completely messes up the whole interface when i initiate an expand or collapse event after dropping (see second image)
    Here is the code i'm using for this solution:
    Code:
    <script type="text/javascript">
        Ext.require(['*']);
    
    
        Ext.onReady(function () {
    
    
            Ext.QuickTips.init();
    
    
            Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));
    
    
    
    
            var viewport = Ext.create('Ext.Viewport', {
                renderTo: 'contentdd',
                id: 'border-example',
                layout: 'border',
                items: [
                    Ext.create('Ext.Component', {
                        region: 'north',
                        height: 32,
                        autoEl: {
                            tag: 'div',
                            html: '<p>north</p>'
                        }
                    }), {
                        region: 'south',
                        contentEl: 'south',
                        split: true,
                        height: 100,
                        minSize: 100,
                        maxSize: 200,
                        collapsible: true,
                        collapsed: true,
                        title: 'South',
                        margins: '0 0 0 0'
                    }, {
                        region: 'east',
                        id: 'east-panel',
                        title: 'East Side',
                        collapsible: true,
                        split: true,
                        width: 225,
                        minSize: 175,
                        maxSize: 400,
                        height: 200,
                        margins: '0 5 0 0',
    
    
                    }, {
                        region: 'west',
                        id: 'west-panel',
                        title: 'West',
                        split: true,
                        width: 200,
                        minWidth: 175,
                        maxWidth: 400,
                        collapsible: true,
                        margins: '0 0 0 5',
                        items: [{
                            title: 'West 1',
                            region: 'north',
                            cls: 'widget',
                            minWidth: 80,
                            height: 100,
                            html: 'First West Panel to be dragged',
                        }, {
                            title: 'West 2',
                            cls: 'widget',
                            region: 'north',
                            minWidth: 80,
                            height: 100,
                            html: 'Second West Panel to be dragged',
                        }],
                    }, {
                        region: 'center',
                        id: 'center-panel',
                        draggable: true,
                        collapsible: true,
                        shadow: true,
                    },
                ]
            });
    
    
            var v = viewport.items.items[6];
            v.dragZone = Ext.create('Ext.dd.DragZone', v.getEl(), {
                ddgroup: 'widgetgroup',
                getDragData: function (e) {
    
    
                    var sourceEl = e.getTarget(v.itemSelector, 10);
                    sourceEl = Ext.get(sourceEl).findParent('.widget');
    
    
                    if (sourceEl) {
                        d = sourceEl.cloneNode(true);
                        d.id = Ext.id();
                        return {
                            ddel: d,
                            sourceEl: sourceEl,
                            repairXY: Ext.fly(sourceEl).getXY(),
                            datas: sourceEl,
    
    
                        }
                    }
                },
    
    
                getRepairXY: function () {
                    return this.dragData.repairXY;
                }
            });
    
    
            v.dropZone = Ext.create('Ext.dd.DropZone',v.getEl(), {
                ddgroup: 'widgetgroup',
    
    
                getTargetFromEvent: function (e) {
                    return e.getTarget('.x-panel-body');
                },
    
    
                onNodeEnter: function (target, dd, e, data) {
                    Ext.fly(target).addCls('my-row-highlight-class');
                },
    
    
                onNodeOut: function (target, dd, e, data) {
                    Ext.fly(target).removeCls('my-row-highlight-class');
                },
    
    
                onNodeOver: function (target, dd, e, data) {
                    return Ext.dd.DropZone.prototype.dropAllowed;
                },
    
    
                onNodeDrop: function (nodeData, source, e, data) {
                    var targetEl = Ext.get(nodeData);
                    var widgettarget = Ext.get(source.id).down("#" + data.datas.id);
                    Ext.get(dd.id).down("#" + data.datas.id).remove();
                    targetEl.appendChild(widgettarget);
                    return true;
                }
            });
    
    
            var w = viewport.items.items[5];
    
    
            w.dragZone = Ext.create('Ext.dd.DragZone', w.getEl(), {
                ddgroup: 'widgetgroup',
                getDragData: function (e) {
    
    
                    var sourceEl = e.getTarget(v.itemSelector, 10);
                    sourceEl = Ext.get(sourceEl).findParent('.widget');
    
    
                    if (sourceEl) {
                        d = sourceEl.cloneNode(true);
                        d.id = Ext.id();
                        return {
                            ddel: d,
                            sourceEl: sourceEl,
                            repairXY: Ext.fly(sourceEl).getXY(),
                            datas: sourceEl,
    
    
                        }
                    }
                },
    
    
                getRepairXY: function () {
                    return this.dragData.repairXY;
                }
            });
    
    
            w.dropZone = Ext.create('Ext.dd.DropZone', w.getEl(), {
                ddgroup: 'widgetgroup',
    
    
                getTargetFromEvent: function (e) {
                    return e.getTarget('.x-panel-body');
                },
    
    
                onNodeEnter: function (target, dd, e, data) {
                    Ext.fly(target).addCls('my-row-highlight-class');
                },
    
    
                onNodeOut: function (target, dd, e, data) {
                    Ext.fly(target).removeCls('my-row-highlight-class');
                },
    
    
                onNodeOver: function (target, dd, e, data) {
                    return Ext.dd.DropZone.prototype.dropAllowed;
                },
    
    
                onNodeDrop: function (target, dd, e, data) {
                    console.log("target w" , target);
                    var targetEl = Ext.get(target);
                    Ext.get(dd.id).down("#" + data.datas.id).remove();
                    targetEl.appendChild(data.datas);
                    return true;
                }
            });
    
    
        });
    </script>
    And to conclude, I'd like to know if you have any idea which solution would be best, seeming that the drag/dropzone solution already handles the reordering in the same parent, i'd rather use it but i'm open to work on the other one if it has to come to it.

    Anyway, thanks in advance for your replies!
    Attached Images

  2. #2
    Sencha User
    Join Date
    May 2013
    Posts
    10
    Vote Rating
    0
    Revingbell is on a distinguished road

      0  

    Default


    So noone can give me any advice at all?

    In addition to what I said in the previous post, issue #4 also happens when i resize any of the areas.

  3. #3
    Sencha - Support Team slemmon's Avatar
    Join Date
    Mar 2009
    Location
    Boise, ID
    Posts
    4,913
    Answers
    371
    Vote Rating
    179
    slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold slemmon is a splendid one to behold

      1  

    Default


    Drag/drop can be tricky under the best circumstances.
    Instead of attempting to rearrange the containing elements of the widgets yourself you might instead see if you can make use of the Ext.util.ComponentDragger class:
    http://docs.sencha.com/extjs/4.2.0/#...mponentDragger

    And in your drop action instead of appending the html element using appendChild you can operate on the component level using the container widget's add / insert methods which should address your issue of collapsing/expanding destroying the new placement of each dragged widget.

    You may also want to read up on the source of the BoxReorder class:
    http://docs.sencha.com/extjs/4.2.0/#...x.BoxReorderer

  4. #4
    Sencha - Architect Dev Team
    Join Date
    Jan 2009
    Location
    Frederick, Maryland
    Posts
    817
    Answers
    57
    Vote Rating
    31
    jminnick has a spectacular aura about jminnick has a spectacular aura about

      0  

    Default


    @Revingbell - Are you still having issues with this?
    Jason Minnick
    Sencha Architect Development Team

  5. #5
    Sencha User
    Join Date
    May 2013
    Posts
    10
    Vote Rating
    0
    Revingbell is on a distinguished road

      0  

    Default


    Actually I explored another way to solve my issues before I got slemmon's response, I used the Portal Demo Example to drag/drop my "widgets" and it's working pretty fine right now, although I don't quite get the whole process that is realized by the Javascript yet .
    To be truthful I haven't actually been putting any thought in slemmon's response as of today, but I read it and it seems that there are some interesting leads in it that might help if I need to use drag/drop zones again.
    I'll be sure to post again here when I'll rush into it to keep you informed of whether it works out or not, but for now I'm exploring the possibilities of the Portal Demo.

    Thanks anyway for your answers!

  6. #6
    Sencha - Architect Dev Team
    Join Date
    Jan 2009
    Location
    Frederick, Maryland
    Posts
    817
    Answers
    57
    Vote Rating
    31
    jminnick has a spectacular aura about jminnick has a spectacular aura about

      0  

    Default


    Okay, I'm building a plugin that will enable BorderLayout regions to become draggable. I plan on wrapping this up soon and passing it along to some of the users in the community to test before releasing it. Let me know if you're interested.
    Jason Minnick
    Sencha Architect Development Team

  7. #7
    Sencha User
    Join Date
    May 2013
    Posts
    10
    Vote Rating
    0
    Revingbell is on a distinguished road

      0  

    Default


    Actually yes, I am VERY interested thanks for offering.

  8. #8
    Sencha - Architect Dev Team
    Join Date
    Jan 2009
    Location
    Frederick, Maryland
    Posts
    817
    Answers
    57
    Vote Rating
    31
    jminnick has a spectacular aura about jminnick has a spectacular aura about

      0  

    Default


    Quote Originally Posted by Revingbell View Post
    Actually yes, I am VERY interested thanks for offering.
    Cool, I'll PM you the plugin when I'm finished.
    Jason Minnick
    Sencha Architect Development Team

Thread Participants: 2

Tags for this Thread