218 lines
6.1 KiB
JavaScript
218 lines
6.1 KiB
JavaScript
/*
|
|
This file is part of Ext JS 3.4
|
|
|
|
Copyright (c) 2011-2013 Sencha Inc
|
|
|
|
Contact: http://www.sencha.com/contact
|
|
|
|
GNU General Public License Usage
|
|
This file may be used under the terms of the GNU General Public License version 3.0 as
|
|
published by the Free Software Foundation and appearing in the file LICENSE included in the
|
|
packaging of this file.
|
|
|
|
Please review the following information to ensure the GNU General Public License version 3.0
|
|
requirements will be met: http://www.gnu.org/copyleft/gpl.html.
|
|
|
|
If you are unsure which license is appropriate for your use, please contact the sales department
|
|
at http://www.sencha.com/contact.
|
|
|
|
Build date: 2013-04-03 15:07:25
|
|
*/
|
|
Ext.ux.Portal = Ext.extend(Ext.Panel, {
|
|
layout : 'column',
|
|
autoScroll : true,
|
|
cls : 'x-portal',
|
|
defaultType : 'portalcolumn',
|
|
|
|
initComponent : function(){
|
|
Ext.ux.Portal.superclass.initComponent.call(this);
|
|
this.addEvents({
|
|
validatedrop:true,
|
|
beforedragover:true,
|
|
dragover:true,
|
|
beforedrop:true,
|
|
drop:true
|
|
});
|
|
},
|
|
|
|
initEvents : function(){
|
|
Ext.ux.Portal.superclass.initEvents.call(this);
|
|
this.dd = new Ext.ux.Portal.DropZone(this, this.dropConfig);
|
|
},
|
|
|
|
beforeDestroy : function() {
|
|
if(this.dd){
|
|
this.dd.unreg();
|
|
}
|
|
Ext.ux.Portal.superclass.beforeDestroy.call(this);
|
|
}
|
|
});
|
|
|
|
Ext.reg('portal', Ext.ux.Portal);
|
|
|
|
Ext.ux.Portal.DropZone = Ext.extend(Ext.dd.DropTarget, {
|
|
|
|
constructor : function(portal, cfg){
|
|
this.portal = portal;
|
|
Ext.dd.ScrollManager.register(portal.body);
|
|
Ext.ux.Portal.DropZone.superclass.constructor.call(this, portal.bwrap.dom, cfg);
|
|
portal.body.ddScrollConfig = this.ddScrollConfig;
|
|
},
|
|
|
|
ddScrollConfig : {
|
|
vthresh: 50,
|
|
hthresh: -1,
|
|
animate: true,
|
|
increment: 200
|
|
},
|
|
|
|
createEvent : function(dd, e, data, col, c, pos){
|
|
return {
|
|
portal: this.portal,
|
|
panel: data.panel,
|
|
columnIndex: col,
|
|
column: c,
|
|
position: pos,
|
|
data: data,
|
|
source: dd,
|
|
rawEvent: e,
|
|
status: this.dropAllowed
|
|
};
|
|
},
|
|
|
|
notifyOver : function(dd, e, data){
|
|
var xy = e.getXY(), portal = this.portal, px = dd.proxy;
|
|
|
|
// case column widths
|
|
if(!this.grid){
|
|
this.grid = this.getGrid();
|
|
}
|
|
|
|
// handle case scroll where scrollbars appear during drag
|
|
var cw = portal.body.dom.clientWidth;
|
|
if(!this.lastCW){
|
|
this.lastCW = cw;
|
|
}else if(this.lastCW != cw){
|
|
this.lastCW = cw;
|
|
portal.doLayout();
|
|
this.grid = this.getGrid();
|
|
}
|
|
|
|
// determine column
|
|
var col = 0, xs = this.grid.columnX, cmatch = false;
|
|
for(var len = xs.length; col < len; col++){
|
|
if(xy[0] < (xs[col].x + xs[col].w)){
|
|
cmatch = true;
|
|
break;
|
|
}
|
|
}
|
|
// no match, fix last index
|
|
if(!cmatch){
|
|
col--;
|
|
}
|
|
|
|
// find insert position
|
|
var p, match = false, pos = 0,
|
|
c = portal.items.itemAt(col),
|
|
items = c.items.items, overSelf = false;
|
|
|
|
for(var len = items.length; pos < len; pos++){
|
|
p = items[pos];
|
|
var h = p.el.getHeight();
|
|
if(h === 0){
|
|
overSelf = true;
|
|
}
|
|
else if((p.el.getY()+(h/2)) > xy[1]){
|
|
match = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pos = (match && p ? pos : c.items.getCount()) + (overSelf ? -1 : 0);
|
|
var overEvent = this.createEvent(dd, e, data, col, c, pos);
|
|
|
|
if(portal.fireEvent('validatedrop', overEvent) !== false &&
|
|
portal.fireEvent('beforedragover', overEvent) !== false){
|
|
|
|
// make sure proxy width is fluid
|
|
px.getProxy().setWidth('auto');
|
|
|
|
if(p){
|
|
px.moveProxy(p.el.dom.parentNode, match ? p.el.dom : null);
|
|
}else{
|
|
px.moveProxy(c.el.dom, null);
|
|
}
|
|
|
|
this.lastPos = {c: c, col: col, p: overSelf || (match && p) ? pos : false};
|
|
this.scrollPos = portal.body.getScroll();
|
|
|
|
portal.fireEvent('dragover', overEvent);
|
|
|
|
return overEvent.status;
|
|
}else{
|
|
return overEvent.status;
|
|
}
|
|
|
|
},
|
|
|
|
notifyOut : function(){
|
|
delete this.grid;
|
|
},
|
|
|
|
notifyDrop : function(dd, e, data){
|
|
delete this.grid;
|
|
if(!this.lastPos){
|
|
return;
|
|
}
|
|
var c = this.lastPos.c,
|
|
col = this.lastPos.col,
|
|
pos = this.lastPos.p,
|
|
panel = dd.panel,
|
|
dropEvent = this.createEvent(dd, e, data, col, c,
|
|
pos !== false ? pos : c.items.getCount());
|
|
|
|
if(this.portal.fireEvent('validatedrop', dropEvent) !== false &&
|
|
this.portal.fireEvent('beforedrop', dropEvent) !== false){
|
|
|
|
dd.proxy.getProxy().remove();
|
|
panel.el.dom.parentNode.removeChild(dd.panel.el.dom);
|
|
|
|
if(pos !== false){
|
|
c.insert(pos, panel);
|
|
}else{
|
|
c.add(panel);
|
|
}
|
|
|
|
c.doLayout();
|
|
|
|
this.portal.fireEvent('drop', dropEvent);
|
|
|
|
// scroll position is lost on drop, fix it
|
|
var st = this.scrollPos.top;
|
|
if(st){
|
|
var d = this.portal.body.dom;
|
|
setTimeout(function(){
|
|
d.scrollTop = st;
|
|
}, 10);
|
|
}
|
|
|
|
}
|
|
delete this.lastPos;
|
|
},
|
|
|
|
// internal cache of body and column coords
|
|
getGrid : function(){
|
|
var box = this.portal.bwrap.getBox();
|
|
box.columnX = [];
|
|
this.portal.items.each(function(c){
|
|
box.columnX.push({x: c.el.getX(), w: c.el.getWidth()});
|
|
});
|
|
return box;
|
|
},
|
|
|
|
// unregister the dropzone from ScrollManager
|
|
unreg: function() {
|
|
Ext.dd.ScrollManager.unregister(this.portal.body);
|
|
Ext.ux.Portal.DropZone.superclass.unreg.call(this);
|
|
}
|
|
});
|