Hybrid View

    Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1
    Ext JS Premium Member
    Join Date
    Jul 2008
    Location
    Germany
    Posts
    34
    Vote Rating
    3
    martinorth is on a distinguished road

      0  

    Default Ext JS 4 Custom Drag and Drop does not work as expected

    Ext JS 4 Custom Drag and Drop does not work as expected


    There is a strange behaviour with this code using ExtJS 4. After dragging the drag element inside the drop zone it is nearly impossible to drag the element back to its original position. It seems that there is a problem with the positioning. Maybe you have to test the code with 3.2 and 4.07 to see the behaviour. Same with the custom drag and drop example at http://www.sencha.com/blog/5-steps-t...p-with-ext-js/ It will work with ExtJS 3 but strange behaviour with 4.07

    I think it could be a bug inside Ext.dd.DD. Maybe alignElWithMouse() has a bug.

    Themes to be the same like: http://www.sencha.com/forum/showthre...tem-up-or-left

    Code:
    <html>
        <head>
            <title>ExtJS Custom Drag'n Drop Demo</title>
            <link rel="stylesheet" type="text/css" href="/extjs/resources/css/ext-all.css" />
            
            
            <style type="text/css">
                
                #dropper {
                    width: 290px;
                    padding-left: 5px;
                    height: 150px;
                    background-color: silver;
                }
                
                #burgerzone {
                    width: 290px;
                    padding-left: 5px;
                    height: 150px;
                }
                
                #dragme, #dropme {
                    border: 1px solid black;
                    margin-bottom: 5px;
                    margin-left: 5px;
                    padding-left: 5px;
                    padding-bottom: 5px;
                    width: 300px;
                }
            </style>
            <script type="text/javascript" src="/extjs/ext-all-debug.js">
            </script>
    
            
            <script type="text/javascript">
                // overrides enthaelt die individuelle Drag and Drop Logik einer Anwendung
                    
                    var overrides = {
                        onInvalidDrop: function(){
                        
                            // onIvalidDrop wird ausgefuehrt, wenn der Burger an eine unzulaessigen Stelle außerhalb
                            // der grauen Flaeche gezogen wurde
                            // hier kann noch zusaetzlicher Code ausgefuehrt werden, z.B. eine extra Logik implementiert werden
                            // im Normalfall setzt man hier nur invalidDrop auf true und wertet dies spaeter in endDrag aus
                            
                            this.invalidDrop = true;
                            
                        },
                        
                        b4StartDrag: function(){
                            if (!this.el) {
                                this.el = Ext.get(this.getEl());
                            }
                            
                            // falls der ganze Drag and Drop Vorgang unguelltig ist, merkt man sich in origPos die 
                            // Ausgangsposition des bewegten Elements und kann das Element spaeter wieder dort positionieren
                            
                            this.origPos = this.el.getXY();
                        },
                        
                        
                        endDrag: function(){
                        
                            // Auswertung von invalidDrop
                            // Ist der Drag and Drop des Burgers unguelltig? 
                            if (this.invalidDrop === true) {
                            
                                // Konfiguration fuer Repair-Animation
                                var anim = {
                                    easing: 'elasticOut',
                                    duration: 1,
                                    scope: this,
                                    callback: function(){
                                        // sobald die Animation beendet ist, wird der Burger wieder 
                                        // an seiner Ausgangsposition angezeigt
                                        this.el.dom.style.position = '';
                                    }
                                };
                                
                                // Repair-Animation
                                // der Burger wird wieder an die Ausgangsposition verschoben
                                this.el.moveTo(this.origPos[0], this.origPos[1], anim);
                                delete this.invalidDrop;
                            }
                            
                        },
                        
                        onDragDrop: function(evtObject, targetElId){
                        
                            // der Burger wird zu einem Ext.Element
                            var dropEl = Ext.get(targetElId);
                            
                            // der Burger wird nur verschoben, wenn Ursprungs- 
                            // und Ziel-Element nicht identisch sind
                            if (this.el.dom.parentNode.id != targetElId) {
                            
                                // der Burger wird zum Kind des Ziel-Elements
                                dropEl.appendChild(this.el);
                                
                                // der Burger ist jetzt ein Kind von dropper
                                // falsche styles sind zu loeschen
                                this.el.dom.style.position = '';
                                debugger;
                            }
                            else {
                                // this was an invalid drop, initiate a repair
                                this.onInvalidDrop();
                            }
                        }
                    
                    };
                
            </script>
            
            <script type="text/javascript">
                Ext.onReady(function(){
                
                    // aus dem HTML-Code des Burgers wird das Ext.Element burgerElement
                    var burgerElement = Ext.get('burger');
                    
                    // dd ist eine Instanz der Klasse Ext.dd.DD
                    // beim instanziieren wird das burgerElement übergeben und 
                    // die DDGroup speisekartenDDGroup angegeben
                    // dd ist kein target
                    var dd = new Ext.dd.DD(burgerElement, 'speisekartenDDGroup', {
                        isTarget: false
                    });
                    
                    // overrides wird in dd kopiert
                    Ext.apply(dd, overrides);
                    
                    // der div Tag mit der id dropper wird als drop target definiert
                    // und ebenfalls der DDGroup speisekartenDDGroup zugewiesen
                    
                    var dragzone = new Ext.dd.DDTarget('burgerzone', 'speisekartenDDGroup');
                    var dropper = new Ext.dd.DDTarget('dropper', 'speisekartenDDGroup');
                    
                });
            </script>
            <body>
                <fieldset id="dragme">
                    <legend>
                        Drag from here
                    </legend>
                    <div id="burgerzone">
                        <img id="burger" alt="burger" src="/assets/images/food/hamburger.jpg" width="100" height="100">
                    </div>
                </fieldset>
                <fieldset id="dropme">
                    <legend>
                        Drop here
                    </legend>
                    <div id="dropper">
                        &nbsp;
                    </div>
                </fieldset>
            </body>
            </html>

  2. #2
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,506
    Vote Rating
    373
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    Do you want this thread to be moved to Bugs Forum?
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid Search Plugin, ExtJS 5 Complex Data Binding using MVVM


  3. #3
    Ext JS Premium Member
    Join Date
    Jul 2008
    Location
    Germany
    Posts
    34
    Vote Rating
    3
    martinorth is on a distinguished road

      0  

    Post maybe solved: bug or feature

    maybe solved: bug or feature


    The method alignElWithMouse() uses absolute and relative positioning.

    Code:
    alignElWithMouse: function(el, iPageX, iPageY) {
            var oCoord = this.getTargetCoord(iPageX, iPageY),
                fly = el.dom ? el : Ext.fly(el, '_dd'),
                elSize = fly.getSize(),
                EL = Ext.Element,
                vpSize;
    
            if (!this.deltaSetXY) {
                vpSize = this.cachedViewportSize = { width: EL.getDocumentWidth(), height: EL.getDocumentHeight() };
                var aCoord = [
                    Math.max(0, Math.min(oCoord.x, vpSize.width - elSize.width)),
                    Math.max(0, Math.min(oCoord.y, vpSize.height - elSize.height))
                ];
                // absolute positioning with fly.setXY()
                fly.setXY(aCoord);
                var newLeft = fly.getLeft(true);
                var newTop  = fly.getTop(true);
                this.deltaSetXY = [newLeft - oCoord.x, newTop - oCoord.y];
            } else {
                vpSize = this.cachedViewportSize;
                // relative positioning with fly.setLeftTop()
                fly.setLeftTop(
                    // problem code
                    Math.max(0, Math.min(oCoord.x + this.deltaSetXY[0], vpSize.width - elSize.width)),
                    Math.max(0, Math.min(oCoord.y + this.deltaSetXY[1], vpSize.height - elSize.height))
                );
            }
    
            this.cachePosition(oCoord.x, oCoord.y);
            this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
            return oCoord;
        }
    The problem is the relative positioning with fly.setLeftTop() and Math.max() with a value of 0. Math.max() with 0 never can be negative so it is not possible to move a drag item to the top(up) or to the left side. Simply removing Math.max() with 0 would do the trick.
    Code:
    <html>
        <head>
            <title>ExtJS Custom Drag'n Drop Demo</title>
            <link rel="stylesheet" type="text/css" href="/extjs/resources/css/ext-all.css" />
            
            
            <style type="text/css">
                
                #dropper {
                    width: 290px;
                    padding-left: 5px;
                    height: 150px;
                    background-color: silver;
                }
                
                #burgerzone {
                    width: 290px;
                    padding-left: 5px;
                    height: 150px;
                }
                
                 #burger {
                    width: 100px;
                    padding: 5px;
                    height: 100px;
                    background-color: red;
                }
                
                #dragme, #dropme {
                    border: 1px solid black;
                    margin-bottom: 5px;
                    margin-left: 5px;
                    padding-left: 5px;
                    padding-bottom: 5px;
                    width: 300px;
                }
            </style>
            <script type="text/javascript" src="/extjs/ext-all-debug-w-comments.js">
            </script>
    
            
            <script type="text/javascript">
                // overrides enthaelt die individuelle Drag and Drop Logik einer Anwendung
                    
                    var overrides = {
                        onInvalidDrop: function(){
                        
                            // onIvalidDrop wird ausgefuehrt, wenn der Burger an eine unzulaessigen Stelle außerhalb
                            // der grauen Flaeche gezogen wurde
                            // hier kann noch zusaetzlicher Code ausgefuehrt werden, z.B. eine extra Logik implementiert werden
                            // im Normalfall setzt man hier nur invalidDrop auf true und wertet dies spaeter in endDrag aus
                            
                            this.invalidDrop = true;
                            
                        },
                        
                        b4StartDrag: function(){
                            if (!this.el) {
                                this.el = Ext.get(this.getEl());
                            }
                            
                            // falls der ganze Drag and Drop Vorgang unguelltig ist, merkt man sich in origPos die 
                            // Ausgangsposition des bewegten Elements und kann das Element spaeter wieder dort positionieren
                            
                            this.origPos = this.el.getXY();
                        },
                        
                        
                        endDrag: function(){
                        
                            // Auswertung von invalidDrop
                            // Ist der Drag and Drop des Burgers unguelltig? 
                            if (this.invalidDrop === true) {
                            
                                // Konfiguration fuer Repair-Animation
                                var anim = {
                                    easing: 'elasticOut',
                                    duration: 1,
                                    scope: this,
                                    callback: function(){
                                        // sobald die Animation beendet ist, wird der Burger wieder 
                                        // an seiner Ausgangsposition angezeigt
                                        this.el.dom.style.position = '';
                                    }
                                };
                                
                                // Repair-Animation
                                // der Burger wird wieder an die Ausgangsposition verschoben
                                this.el.moveTo(this.origPos[0], this.origPos[1], anim);
                                delete this.invalidDrop;
                            }
                            
                        },
                        
                        onDragDrop: function(evtObject, targetElId){
                        
                            // der Burger wird zu einem Ext.Element
                            var dropEl = Ext.get(targetElId);
                            
                            // der Burger wird nur verschoben, wenn Ursprungs- 
                            // und Ziel-Element nicht identisch sind
                            if (this.el.dom.parentNode.id != targetElId) {
                            
                                // der Burger wird zum Kind des Ziel-Elements
                                dropEl.appendChild(this.el);
                                
                                // der Burger ist jetzt ein Kind von dropper
                                // falsche styles sind zu loeschen
                                this.el.dom.style.position = '';
    
                            }
                            else {
                                // this was an invalid drop, initiate a repair
                                this.onInvalidDrop();
                            }
                        },
                        alignElWithMouse: function(el, iPageX, iPageY) {
                            var oCoord = this.getTargetCoord(iPageX, iPageY),
                                fly = el.dom ? el : Ext.fly(el, '_dd'),
                                elSize = fly.getSize(),
                                EL = Ext.Element,
                                vpSize;
    
                            if (!this.deltaSetXY) {
                                vpSize = this.cachedViewportSize = { width: EL.getDocumentWidth(), height: EL.getDocumentHeight() };
                                var aCoord = [
                                    Math.max(0, Math.min(oCoord.x, vpSize.width - elSize.width)),
                                    Math.max(0, Math.min(oCoord.y, vpSize.height - elSize.height))
                                ];
                                fly.setXY(aCoord);
                                var newLeft = fly.getLeft(true);
                                var newTop  = fly.getTop(true);
                                this.deltaSetXY = [newLeft - oCoord.x, newTop - oCoord.y];
                            } else {
                                vpSize = this.cachedViewportSize;
                                fly.setLeftTop(
                                    Math.min(oCoord.x + this.deltaSetXY[0], vpSize.width - elSize.width),
                                    Math.min(oCoord.y + this.deltaSetXY[1], vpSize.height - elSize.height)
                                );
                            }
    
                            this.cachePosition(oCoord.x, oCoord.y);
                            this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
                            return oCoord;
                        }
                    
                    };
                
            </script>
            
            <script type="text/javascript">
                Ext.onReady(function(){
                
                    // aus dem HTML-Code des Burgers wird das Ext.Element burgerElement
                    var burgerElement = Ext.get('burger');
                    
                    // dd ist eine Instanz der Klasse Ext.dd.DD
                    // beim instanziieren wird das burgerElement übergeben und 
                    // die DDGroup speisekartenDDGroup angegeben
                    // dd ist kein target
                    var dd = new Ext.dd.DD(burgerElement, 'speisekartenDDGroup', {
                        isTarget: false
                    });
                    
                    // overrides wird in dd kopiert
                    Ext.apply(dd, overrides);
                    
                    // der div Tag mit der id dropper wird als drop target definiert
                    // und ebenfalls der DDGroup speisekartenDDGroup zugewiesen
                    
                    var dragzone = new Ext.dd.DDTarget('burgerzone', 'speisekartenDDGroup');
                    var dropper = new Ext.dd.DDTarget('dropper', 'speisekartenDDGroup');
                    
                });
            </script>
            <body>
                <div align="center">
                    <fieldset id="dragme">
                        <legend>
                            Drag from here
                        </legend>
                        <div id="burgerzone">
                            <div id="burger">Burger</div>
                        </div>
                    </fieldset>
                    <fieldset id="dropme">
                        <legend>
                            Drop here
                        </legend>
                        <div id="dropper">
                            &nbsp;
                        </div>
                    </fieldset>
                </div>
            </body>
            </html>

  4. #4
    Sencha - Community Support Team jsakalos's Avatar
    Join Date
    Apr 2007
    Location
    Slovakia
    Posts
    27,506
    Vote Rating
    373
    jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future jsakalos has a brilliant future

      0  

    Default


    Is that solved then? Or should I move it to Bugs?
    Jozef Sakalos, aka Saki

    Education, extensions and services for developers at new http://extjs.eu
    News: Grid Search Plugin, ExtJS 5 Complex Data Binding using MVVM


  5. #5
    Ext JS Premium Member
    Join Date
    Jul 2008
    Location
    Germany
    Posts
    34
    Vote Rating
    3
    martinorth is on a distinguished road

      0  

    Default


    Move it to bugs because it only works with an override.

Thread Participants: 1