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>