/******************************************************************************
* sdsDragDrop.js
*******************************************************************************
Drag and Drop Manager
*******************************************************************************
*                                                                             *
* Copyright 2008									                          *
*                                                                             *
******************************************************************************/
function SdsDragAndDropObject(type, data, html)
{
	this._type = type;
	this._data = data;
	this._html = html;
}

SdsDragAndDropObject.prototype.getType = function()
{
	return this._type;
}

SdsDragAndDropObject.prototype.getData = function()
{
	return this._data;
}
SdsDragAndDropObject.prototype.getHtml = function()
{
	return this._html;
}
function SdsAbstractDragAndDropTarget(rootElement)
{
	if(rootElement) {
		this._rootElement = rootElement;
	}
}

SdsAbstractDragAndDropTarget.prototype.isAlive = function()
{
	return true;
}

SdsAbstractDragAndDropTarget.prototype.acceptsType = function(type)
{
	alert("la méthode 'acceptsType' de la cible du drag and drop n'est pas implémentée\n");
	return false;
}
SdsAbstractDragAndDropTarget.prototype.accepts = function(dragObject, element)
{
	alert("la méthode 'accepts' de la cible du drag and drop n'est pas implémentée\n");
	return false;
}

SdsAbstractDragAndDropTarget.prototype.receives = function(dragAndDropObject)
{
	alert("la méthode 'receives' de la cible du drag and drop n'est pas implémentée\n");
	return;
}

function SdsDragAndDropManager()
{
	this._targets = [];
	this._documents = [];
	this._bestManager = null;
	this._acceptedTypes = {};
}

SdsDragAndDropManager.prototype.getBestManager = function()
{
	if(this._bestManager) return this._bestManager;
	var f = window;
	if(f.frames.parent.sdsDragAndDropManager) {
		f = f.frames.parent;
	} else {
		while(f.frames.parent != f && f.frames.parent.sdsDragAndDropManager) {
			f = frames.parent;
		}
	}
	return f.sdsDragAndDropManager;
}

SdsDragAndDropManager.prototype.hasTargetForType = function(type)
{
	if(this._acceptedTypes[type]) return true;
	for(var i=0;i<this._targets.length;i++) {
		var target = this._targets[i];
		try {
			if(target.acceptsType(type)) {
				this._acceptedTypes[type] = true;
				return true;
			}
		} catch(e) {
			this.removeAllUnloadedTargets();
		}
	}
	return false;
}

SdsDragAndDropManager.prototype.start = function(ev, dragObject)
{
	var manager = this.getBestManager();
	if(manager != this) return manager.start(dragObject);
	this._dragObject = dragObject;
	var de = this._dragElement;
	if(de == null) {
		de = this._dragElement = document.createElement("div");
		document.body.appendChild(this._dragElement);
		de.style.backgroundColor = "#C0C0C0";
		de.style.position = "absolute";
		de.style.border = "1px solid black";
		de.style.padding = "4px";
	}
	de.innerHTML = dragObject.getHtml();
	de.style.display = "block";
	var frames = window.frames;
	this.addEvent(frames.top.document.body, "mousemove", this.dragmove);
	this.addEvent(frames.top.document.body, "mouseup", this.mouseup);
	for(var i=frames.length-1;i>=0;i--) {
		var frame = frames[i];
		this.addEvent(frame.document.body, "mousemove", this.dragmove);
		this.addEvent(frame.document.body, "mouseup", this.mouseup);
	}
	if(!document.all) {
		ev.stopPropagation();
	}
	//alert(frames.length);
}

SdsDragAndDropManager.prototype.dragmove = function(ev)
{
    ev || (ev = window.event);
    var element = document.all ? ev.srcElement : ev.target;
	var manager = sdsDragAndDropManager.getBestManager();
	return manager.ondragmove(ev, element);
}


SdsDragAndDropManager.prototype.mouseup = function(ev)
{
    ev || (ev = window.event);
    var element = document.all ? ev.srcElement : ev.target;
	var manager = sdsDragAndDropManager.getBestManager();
	return manager.onmouseup(ev, element);
}

SdsDragAndDropManager.prototype.ondragmove = function(ev, element)
{
	var de = this._dragElement;
	var frames = window.frames;
	var x, y;
	if(document.all) {
		x = ev.screenX - frames.top.screenLeft + 2;
		y = ev.screenY - frames.top.screenTop - 10;
	} else {
		var topWindow = window.frames.top;
		x = ev.screenX + 2;
		y = ev.screenY - (topWindow.outerHeight - topWindow.innerHeight) - 10;
	}
	de.style.left = x + "px";
	de.style.top = y + "px";
	de.style.display = "block";
	for(var i=0;i<this._targets.length;i++) {
		var target = this._targets[i];
		try {
			target.accepts(this._dragObject, element, ev);
		} catch(e) {
			this.removeAllUnloadedTargets();
		}
	}
	if(!document.all) {
		var w = element.ownerDocument.defaultView;
		selection = w.getSelection();
		selection.removeAllRanges();
	}
	return true;
}

SdsDragAndDropManager.prototype.onmouseup = function(ev, element)
{
	var frames = window.frames;
	this.removeEvent(frames.top.document.body, "mousemove", this.dragmove);
	this.removeEvent(frames.top.document.body, "mouseup", this.mouseup);
	for(var i=0;i<frames.length;i++) {
		var frame = frames[i];
		this.removeEvent(frame.document.body, "mousemove", this.dragmove);
		this.removeEvent(frame.document.body, "mouseup", this.mouseup);
	}
	if(this._dragElement != null) {
		this._dragElement.style.display = "none";
	}
	for(var i=0;i<this._targets.length;i++) {
		var target = this._targets[i];
		try {
			target.receives(this._dragObject, element);
		} catch(e) {
			this.removeAllUnloadedTargets();
		}
	}
	this._dragObject = null;
	return true;
}

SdsDragAndDropManager.prototype.stop = function()
{
	var manager = this.getBestManager();
	if(manager != this) return manager.stop();
}
SdsDragAndDropManager.prototype.getWindowFromDocument = function(doc)
{
	if(document.all) return doc.frames.self;
	else return doc.defaultView;
}
SdsDragAndDropManager.prototype.addTarget = function(target, doc)
{
	var manager = this.getBestManager();
	if(manager != this) return manager.addTarget(target, doc);
	this._targets[this._targets.length] = target;
	var found = false;
	for(var i=0;i<this._documents.length;i++) {
		if(this._documents[i] == doc) found = true;
	}
	if(!found) {
		this.addEvent(this.getWindowFromDocument(doc), "unload", this.unload);
	}
	this._documents[this._documents.length] = doc;
}

SdsDragAndDropManager.prototype.unload = function(ev)
{
	var manager = sdsDragAndDropManager.getBestManager();
	manager.removeAllUnloadedTargets();
}

SdsDragAndDropManager.prototype.removeAllUnloadedTargets = function()
{
	var targets = [];
	var documents = [];
	for(var i=0;i<this._targets.length;i++) {
		var target = this._targets[i];
		var doc = this._documents[i];
		try {
			target.isAlive();
			targets[targets.length] = target;
			documents[documents.length] = doc;
		} catch(e) {
		}
	}
	this._targets = targets;
	this._documents = documents;
	this._acceptedTypes = {};
}

SdsDragAndDropManager.prototype.addEvent = function(element, evname, func, capture) 
{
    if (element.attachEvent) { // IE
        element.attachEvent("on" + evname, func);
    } else if (element.addEventListener) { // Gecko / W3C
        element.addEventListener(evname, func, capture != false);
    } else {
        element["on" + evname] = func;
    }
}

SdsDragAndDropManager.prototype.removeEvent = function(element, evname, func) 
{
	if (element.detachEvent) { // IE
		element.detachEvent("on" + evname, func);
	} else if (element.removeEventListener) { // Gecko / W3C
		element.removeEventListener(evname, func, true);
	} else {
		element["on" + evname] = null;
	}
}

window.sdsDragAndDropManager = new SdsDragAndDropManager();
