// DragHelper
var __aspxDragHelper = null;

ASPxClientDragHelper = _aspxCreateClass(null, {
	constructor: function(e, root, clone){
	    if(__aspxDragHelper != null) __aspxDragHelper.cancelDrag();
        this.dragArea = 5;
        this.lastX = e.clientX;
        this.lastY = e.clientY;
        this.canDrag = true; 
        if(typeof(root) == "string") 
            root = _aspxGetParentByTagName(_aspxGetEventSource(e), root);
        this.obj = root && root != null ? root : _aspxGetEventSource(e);
        this.clone = clone;
        this.dragObj = null; 
        this.additionalObj = null;
        //events
        this.onDoClick = new Function();
        this.onEndDrag = new Function();
        this.onCancelDrag = new Function();
        this.onDragDivCreating = new Function();
        this.onCloneCreating = null;
        this.onCloneCreated = new Function();
        
        this.dragDiv = null;
        __aspxDragHelper = this;
    },    
    drag: function(e) {
        if(!this.canDrag) return;
        if(!this.isDragging()) {
            if(!this.isOutOfDragArea(e.clientX, e.clientY)) 
                return;
            this.startDragCore(e);
        }
        if(__aspxIE && !_aspxGetIsLeftButtonPressed(e)) {
            this.cancelDrag(e);
            return;
        }
        this.clearSelection();
        this.dragCore(e);
    },
    clearSelection: function() {
        if(!window.getSelection) return;
        var sel = window.getSelection(); 
        if(sel && sel.removeAllRanges) {
            sel.removeAllRanges() ; 
        }
    },
    startDragCore: function(e) {
        //this function overrides in: ASPxScheduler
        this.dragObj = this.clone != true ? this.obj : this.createClone();
    },
    dragCore: function(e) {
        //this function overrides in: ASPxScheduler
        var nx = this.dragObj.offsetLeft + e.clientX - this.lastX;
        var ny = this.dragObj.offsetTop + e.clientY - this.lastY;
        this.dragObj.style.left = nx + "px";
        this.dragObj.style.top = ny + "px";
        this.lastX = e.clientX;
        this.lastY = e.clientY;
    },
    endDrag: function(e) {
        if(!this.isDragging() && !this.isOutOfDragArea(e.clientX, e.clientY)) 
            this.onDoClick(this);
        else this.onEndDrag(this);
        this.cancelDrag();
    },
    cancelDrag: function() {
        if(this.dragDiv != null) {
            document.body.removeChild(this.dragDiv);
            this.dragDiv = null;
        }
        this.onCancelDrag(this);
        __aspxDragHelper = null;
    },
    isDragging: function() {
       //this function overrides in: ASPxScheduler        
        return this.dragObj != null;
    },
    createClone: function() {
        this.dragDiv = document.createElement("div");
        this.onDragDivCreating(this, this.dragDiv);
        this.dragDiv.style.position = "absolute";
        this.dragDiv.style.cursor = "move";
        this.dragDiv.style.left = _aspxGetAbsoluteX(this.obj) + "px";
        this.dragDiv.style.top = _aspxGetAbsoluteY(this.obj) + "px";
        this.dragDiv.style.width = this.obj.offsetWidth + "px";
        this.dragDiv.style.height = this.obj.offsetHeight + "px";
        this.dragDiv.select = DragHelper_onselectstart;
        this.dragDiv.style.zIndex = 20000; //TODO
        this.dragDiv.style.padding = "0px";
        this.dragDiv.style.margin = "0px";
        this.dragDiv.style.borderStyle = "none";
        this.dragDiv.style.borderWidth = "0px";
        this.dragDiv.style.backgroundColor = "transparent";
        var clone = this.creatingClone();
        this.onCloneCreated(clone);
        this.dragDiv.appendChild(clone);
        document.body.appendChild(this.dragDiv);
        return this.dragDiv;
    },
    creatingClone: function() {
        var clone = this.obj.cloneNode(true);
        if(!_aspxIsExists(this.onCloneCreating)) return clone;
        return this.onCloneCreating(clone);
    },
    addElementToDragDiv: function(element) {
        if(this.dragDiv == null) return;
        this.additionalObj = element.cloneNode(true);
        this.additionalObj.style.visibility = "visible";
        this.dragDiv.appendChild(this.additionalObj);
    },
    removeElementFromDragDiv: function() {
        if(this.additionalObj == null || this.dragDiv == null) return;
        this.dragDiv.removeChild(this.additionalObj);
        this.additionalObj = null;
    },
    isOutOfDragArea: function(newX, newY) {
        return Math.max(Math.abs(newX - this.lastX), Math.abs(newY - this.lastY)) >= this.dragArea;
    }
});

function DragHelper_onmouseup(e) {
    if(__aspxDragHelper != null) {
        __aspxDragHelper.endDrag(e);
        return true;
    }
}
function DragHelper_onmousemove(e) {
    if(__aspxDragHelper != null) {
        __aspxDragHelper.drag(e);
        return true;
    }
}
function DragHelper_onkeydown(e) {
    if(__aspxDragHelper == null) return;
    if(e.keyCode == 27) 
        __aspxDragHelper.cancelDrag();
    return true;
}
function DragHelper_onselectstart(e) {
    if(__aspxDragHelper != null) {
        document.selection.empty();
        return false;
    }
}

_aspxAttachEventToDocument("mouseup", DragHelper_onmouseup);
_aspxAttachEventToDocument("mousemove", DragHelper_onmousemove);
_aspxAttachEventToDocument("keydown", DragHelper_onkeydown);
_aspxAttachEventToDocument("selectstart", DragHelper_onselectstart);

// CursorTargets
var __aspxCursorTargets = null;

ASPxClientCursorTargets = _aspxCreateClass(null, {
    constructor: function() {
        this.list = new Array();
        this.starttargetElement = null;
        this.starttargetTag = 0;
        this.oldtargetElement = null;
        this.oldtargetTag = 0;
        this.targetElement = null;
        this.targetTag = 0;
        this.x = 0;
        this.y = 0;
        this.removedX = 0;
        this.removedY = 0;
        this.removedWidth = 0;
        this.removedHeight = 0;
        //events
        this.onTargetChanging = new Function();
        this.onTargetChanged = new Function();
        __aspxCursorTargets = this;
    },
    addElement: function(element) {
        if(!this.canAddElement(element)) return null;
        var target = new ASPxClientCursorTarget(element);
        this.list.push(target);
        return target;
    },
    removeElement: function(element) {
		for(var i = 0; i < this.list.length; i++)
			if(this.list[i].element == element) {
				this.list.splice(i, 1);
				return;
			}
    },
    addParentElement: function(parent, child) {
        var target = this.addElement(parent);
        if(target != null) {
            target.targetElement = child;
        }
        return target;
    },
    RegisterTargets: function(element, idPrefixArray) {
		this.addFunc = this.addElement;
		this.RegisterTargetsCore(element, idPrefixArray);
    },
    UnregisterTargets: function(element, idPrefixArray) {
		this.addFunc = this.removeElement;
		this.RegisterTargetsCore(element, idPrefixArray);
    },
    RegisterTargetsCore: function(element, idPrefixArray) {
		if(element == null) return;		
        for(var i = 0; i < idPrefixArray.length; i++) 
            this.RegisterTargetCore(element, idPrefixArray[i]);
    },
    RegisterTargetCore: function(element, idPrefix) {
        if(!_aspxIsExists(element.id)) return;
        if(element.id.indexOf(idPrefix) > -1) 
            this.addFunc(element);
        for(var i = 0; i < element.childNodes.length; i ++) 
            this.RegisterTargetCore(element.childNodes[i], idPrefix);
    },
    
    canAddElement: function(element) {
        if(element == null) return false;
        for(var i = 0; i < this.list.length; i ++) {
            if(this.list[i].targetElement == element) return false;
        }
        return element.style.visibility != "hidden";
    },
    removeInitialTarget: function(x, y) {
        var el = this.getTarget(x  + _aspxGetDocumentScrollLeft(), y  + _aspxGetDocumentScrollTop());
        if(el == null) return;
        this.removedX = _aspxGetAbsoluteX(el);
        this.removedY = _aspxGetAbsoluteY(el);
        this.removedWidth = el.offsetWidth;
        this.removedHeight = el.offsetHeight;
    },
    getTarget: function(x, y) {
        for(var i = 0; i < this.list.length; i ++) {
            if(this.list[i].contains(x, y))
                return this.list[i].targetElement;
        }
        return null;
    },
    targetChanged: function(element, tag) {
        this.targetElement = element;
        this.targetTag = tag; 
        this.onTargetChanging(this);
        if(this.oldtargetElement != this.targetElement || this.oldtargetTag != this.targetTag) {
            this.onTargetChanged(this);
            this.oldtargetElement = this.targetElement;
            this.oldtargetTag = this.targetTag;
        }
    },
    cancelChanging: function() {
		this.targetElement = this.oldtargetElement;
		this.targetTag = this.oldtargetTag;
    },
    isLeftPartOfElement: function() {
        if(this.targetElement == null) return true;
        var left = this.x - this.targetElementX();
        return left < this.targetElement.offsetWidth / 2; 
    },
    isTopPartOfElement: function() {
        if(this.targetElement == null) return true;
        var top = this.y - this.targetElementY();
        return top < this.targetElement.offsetHeight / 2; 
    },
    targetElementX: function() {
        return this.targetElement != null ? _aspxGetAbsoluteX(this.targetElement) : 0;
    },
    targetElementY: function() {
        return this.targetElement != null ? _aspxGetAbsoluteY(this.targetElement) : 0;
    },
    onmousemove: function(e) {
        this.doTargetChanged(e); 
    },
    onmouseup: function(e) {
        this.doTargetChanged(e); 
        __aspxCursorTargets = null;    
    },
    doTargetChanged: function(e) {
        this.x = e.clientX + _aspxGetDocumentScrollLeft();
        this.y = e.clientY + _aspxGetDocumentScrollTop();
        if(this.inRemovedBounds(this.x, this.y)) return; 
        this.targetChanged(this.getTarget(this.x, this.y), 0); 
    },
    inRemovedBounds: function(x, y) {
        if(this.removedWidth == 0) return false;
        return x > this.removedX && x < (this.removedX + this.removedWidth) &&
            y > this.removedY && y < (this.removedY + this.removedHeight);
    }
});

ASPxClientCursorTarget = _aspxCreateClass(null, {
    constructor: function(element) {
        this.element = element;
        this.targetElement = element;
        this.absoluteX = _aspxGetAbsoluteX(element);
        this.absoluteY = _aspxGetAbsoluteY(element);
    },
    contains: function(x, y) {
        return x >= this.absoluteX && x <= this.absoluteX + this.element.offsetWidth &&
            y >= this.absoluteY && y <= this.absoluteY + this.element.offsetHeight;
    }
});

function CursorTarget_onmouseup(e) {
    if(__aspxCursorTargets != null) {
        __aspxCursorTargets.onmouseup(e);
        return true;
    }
}

function CursorTarget_onmousemove(e) {
    if(__aspxCursorTargets != null) {
        __aspxCursorTargets.onmousemove(e);
        return true;
    }
}

_aspxAttachEventToDocument("mouseup", CursorTarget_onmouseup);
_aspxAttachEventToDocument("mousemove", CursorTarget_onmousemove);