Code:
Ext.override(Ext.lib.Region, {
/**
* Returns the shortest distance between this Region and another Region.
* Either or both Regions may be Points.
* @param {Region} r The other Region
* @return {Number} The shortest distance in pixels between the two Regions.
*/
getDistanceBetween: function(r) {
// We may need to mutate r, so make a copy.
r = Ext.apply({}, r);
// Translate r to the left of this
if (r.left > this.right) {
var rWidth = r.right - r.left;
r.left = this.left - (r.left - this.right) - rWidth;
r.right = r.left + rWidth;
}
// Translate r above this
if (r.top > this.bottom) {
var rHeight = r.bottom - r.top;
r.top = this.top - (r.top - this.bottom) - rHeight;
r.bottom = r.top + rHeight;
}
// If r is directly above
if (r.right > this.left) {
return this.top - r.bottom;
}
// If r is directly to the left
if (r.bottom > this.top) {
return this.left - r.right;
}
// r is on a diagonal path
return Math.round(Math.sqrt(Math.pow(this.top - r.bottom, 2) + Math.pow(this.left - r.right, 2)));
}
});
/* Window Edge Snapping for Extjs
* Version: 1.6
*
* Copyright (c) 2008-2009 - David W Davis, All Rights Reserved
*
* xantus@xantus.org
* http://xant.us/
# http://extjs.com/forum/showthread.php?t=55213
*
* License: Same as Extjs 2.0
*
* Please do not remove this header
*/
Ext.namespace( 'Ext.ux.WindowSnap' );
// either create your own subclass and extend, or override Ext.Window directly
Ext.override( Ext.Window, {
initDraggable: function() {
this.dd = new Ext.ux.WindowSnap.DD(this);
}
});
// eventually these options should be taken from the window object
// but since Ext.Window does not pass a config obj to Ext.Window.DD
// we'll just set them here
Ext.ux.WindowSnap = {
version: '1.6',
snapRange: 20, // px
dragSnap: false,
dropSnap: true,
animateDropSnap: true
};
Ext.ux.WindowSnap.DD = function() {
Ext.ux.WindowSnap.DD.superclass.constructor.apply(this,arguments);
};
Ext.extend( Ext.ux.WindowSnap.DD, Ext.Window.DD, {
startDrag: function() {
Ext.ux.WindowSnap.DD.superclass.startDrag.apply(this,arguments);
if ( Ext.ux.WindowSnap.dragSnap ) {
this._getSnapData();
}
},
endDrag: function() {
Ext.ux.WindowSnap.DD.superclass.endDrag.apply(this,arguments);
if ( Ext.ux.WindowSnap.dropSnap ) {
this._getSnapData();
var pos = this.win.getPosition();
this.setSnapXY( this.win.el, pos[0], pos[1], true );
}
this.snapDD = [];
},
alignElWithMouse: function(el, iPageX, iPageY) {
var oCoord = this.getTargetCoord(iPageX, iPageY);
var fly = el.dom ? el : Ext.fly(el, '_dd');
if (!this.deltaSetXY) {
var aCoord = [oCoord.x, oCoord.y];
fly.setXY(aCoord);
var newLeft = fly.getLeft(true);
var newTop = fly.getTop(true);
this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
} else {
if ( Ext.ux.WindowSnap.dragSnap ) {
this.setSnapXY( fly, oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1] );
} else {
fly.setLeftTop( oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1] );
}
}
this.cachePosition(oCoord.x, oCoord.y);
this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
return oCoord;
},
setSnapXY: function( fly, x, y, drop ) {
var range = Ext.ux.WindowSnap.snapRange;
// Calculate the drag/drop Window's Region.
var r = drop ? this.win.el.getRegion() : new Ext.lib.Region(y, x + this.win.el.getWidth, y + this.win.el.getHeight(), x);
// Find the nearest other Window
var nearestDistance = Number.MAX_VALUE;
var nearest;
for ( var i = 0, len = this.snapDD.length; i < len; i++ ) {
var distance = r.getDistanceBetween(this.snapDD[i]);
if (distance < nearestDistance) {
nearest = this.snapDD[i];
nearestDistance = distance;
}
}
// If its within the range, snap to it.
if (nearestDistance <= range) {
if (r.right < nearest.left) {
x = nearest.left - this.win.el.getWidth();
} else if (r.left > nearest.right) {
x = nearest.right;
}
if (r.bottom < nearest.top) {
y = nearest.top - this.win.el.getHeight();
} else if (r.top > nearest.bottom) {
y = nearest.bottom;
}
}
// slide the window to the edge or just snap it
if ( drop && Ext.ux.WindowSnap.animateDropSnap ) {
fly.moveTo( x, y, { easing: 'bounceOut', duration: .3 } );
} else {
fly.setLeftTop( x, y );
}
},
_getSnapData: function() {
this.snapDD = [];
var win = this.win;
win.manager.each(function(w) {
if (w && w.isVisible() && (win !== w)) {
this.snapDD.push( w.el.getRegion() );
}
}, this);
}
});