/**
* @class Ext.dd.StatusProxy
* A specialized drag proxy that supports a drop status icon, {@link Ext.Layer} styles and auto-repair. This is the
* default drag proxy used by all Ext.dd components.
* @constructor
* @param {Object} config
*/
Ext.define('Ext.dd.StatusProxy', {
animRepair: false,
constructor: function(config){
Ext.apply(this, config);
this.id = this.id || Ext.id();
this.proxy = Ext.createWidget('component', {
floating: true,
id: this.id,
html: '<div class="' + Ext.baseCSSPrefix + 'dd-drop-icon"></div>' +
'<div class="' + Ext.baseCSSPrefix + 'dd-drag-ghost"></div>',
cls: Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed,
shadow: !config || config.shadow !== false,
renderTo: document.body
});
this.el = this.proxy.el;
this.el.show();
this.el.setVisibilityMode(Ext.core.Element.VISIBILITY);
this.el.hide();
this.ghost = Ext.get(this.el.dom.childNodes[1]);
this.dropStatus = this.dropNotAllowed;
},
/**
* @cfg {String} dropAllowed
* The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").
*/
dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
/**
* @cfg {String} dropNotAllowed
* The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").
*/
dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
/**
* Updates the proxy's visual element to indicate the status of whether or not drop is allowed
* over the current target element.
* @param {String} cssClass The css class for the new drop status indicator image
*/
setStatus : function(cssClass){
cssClass = cssClass || this.dropNotAllowed;
if(this.dropStatus != cssClass){
this.el.replaceCls(this.dropStatus, cssClass);
this.dropStatus = cssClass;
}
},
/**
* Resets the status indicator to the default dropNotAllowed value
* @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
*/
reset : function(clearGhost){
this.el.dom.className = Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed;
this.dropStatus = this.dropNotAllowed;
if(clearGhost){
this.ghost.update("");
}
},
/**
* Updates the contents of the ghost element
* @param {String/HTMLElement} html The html that will replace the current innerHTML of the ghost element, or a
* DOM node to append as the child of the ghost element (in which case the innerHTML will be cleared first).
*/
update : function(html){
if(typeof html == "string"){
this.ghost.update(html);
}else{
this.ghost.update("");
html.style.margin = "0";
this.ghost.dom.appendChild(html);
}
var el = this.ghost.dom.firstChild;
if(el){
Ext.fly(el).setStyle('float', 'none');
}
},
/**
* Returns the underlying proxy {@link Ext.Layer}
* @return {Ext.Layer} el
*/
getEl : function(){
return this.el;
},
/**
* Returns the ghost element
* @return {Ext.core.Element} el
*/
getGhost : function(){
return this.ghost;
},
/**
* Hides the proxy
* @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
*/
hide : function(clear) {
this.proxy.hide();
if (clear) {
this.reset(true);
}
},
/**
* Stops the repair animation if it's currently running
*/
stop : function(){
if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
this.anim.stop();
}
},
/**
* Displays this proxy
*/
show : function() {
this.proxy.show();
this.proxy.toFront();
},
/**
* Force the Layer to sync its shadow and shim positions to the element
*/
sync : function(){
this.proxy.el.sync();
},
/**
* Causes the proxy to return to its position of origin via an animation. Should be called after an
* invalid drop operation by the item being dragged.
* @param {Array} xy The XY position of the element ([x, y])
* @param {Function} callback The function to call after the repair is complete.
* @param {Object} scope The scope (<code>this</code> reference) in which the callback function is executed. Defaults to the browser window.
*/
repair : function(xy, callback, scope){
this.callback = callback;
this.scope = scope;
if (xy && this.animRepair !== false) {
this.el.addCls(Ext.baseCSSPrefix + 'dd-drag-repair');
this.el.hideUnders(true);
this.anim = this.el.animate({
duration: this.repairDuration || 500,
easing: 'ease-out',
to: {
x: xy[0],
y: xy[1]
},
stopAnimation: true,
callback: this.afterRepair,
scope: this
});
} else {
this.afterRepair();
}
},
// private
afterRepair : function(){
this.hide(true);
if(typeof this.callback == "function"){
this.callback.call(this.scope || this);
}
this.callback = null;
this.scope = null;
},
destroy: function(){
Ext.destroy(this.ghost, this.proxy, this.el);
}
});