/************************************************************************************************************
Drag and drop folder tree
Copyright (C) 2006  DTHMLGoodies.com, Alf Magne Kalleland

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

Dhtmlgoodies.com., hereby disclaims all copyright interest in this script
written by Alf Magne Kalleland.

Alf Magne Kalleland, 2006
Owner of DHTMLgoodies.com

************************************************************************************************************/	
		
	var JSTreeObj;
	var treeUlCounter = 0;
	var nodeId = 1;
		
	/* Constructor */
	function JSDragDropTree()
	{
		var idOfTree;
		var imageFolder ="M/i/";
		var folderImage;
		//var plusImage;
		//var minusImage;
		var maximumDepth;
		var dragNode_source;
		var dragNode_parent;
		var dragNode_sourceNextSib;
		var dragNode_noSiblings;
		var ajaxObjects;
		
		var dragNode_destination;
		var floatingContainer;
		var dragDropTimer;
		var dropTargetIndicator;
		var insertAsSub;
		var indicator_offsetX;
		var indicator_offsetX_sub;
		var indicator_offsetY;
		
		this.imageFolder = 'M/i/';

		this.maximumDepth = 6;
		var messageMaximumDepthReached;
		//var filePathRenameItem;
		//var filePathDeleteItem;
		//var additionalRenameRequestParameters = {};
		//var additionalDeleteRequestParameters = {};

		var renameAllowed=false;
		var deleteAllowed=false;
		var currentlyActiveItem;
		var contextMenu;
		var currentItemToEdit;		// Reference to item currently being edited(example: renamed)
		var helpObj;
		
		this.contextMenu = false;
		this.floatingContainer = document.createElement('DIV');
		this.floatingContainer.style.position = 'absolute';
		this.floatingContainer.style.display='none';
		this.floatingContainer.id = 'floatingContainer';
		this.insertAsSub = false;
		document.body.appendChild(this.floatingContainer);
		this.dragDropTimer = -1;
		this.dragNode_noSiblings = false;
		this.currentItemToEdit = false;
		
		if(document.all){
			this.indicator_offsetX = 2;	// Offset position of small black lines indicating where nodes would be dropped.
			this.indicator_offsetX_sub = 4;
			this.indicator_offsetY = 0;
		}else{
			this.indicator_offsetX = 1;	// Offset position of small black lines indicating where nodes would be dropped.
			this.indicator_offsetX_sub = 3;
			this.indicator_offsetY = 2;			
		}
		if(navigator.userAgent.indexOf('Opera')>=0){
			this.indicator_offsetX = 2;	// Offset position of small black lines indicating where nodes would be dropped.
			this.indicator_offsetX_sub = 3;
			this.indicator_offsetY = -7;				
		}

		this.messageMaximumDepthReached = ''; // Use '' if you don't want to display a message 
		
		//	this.renameAllowed = true;
		//	this.deleteAllowed = true;
		this.currentlyActiveItem = false;
		//	this.filePathRenameItem = 'folderTree_updateItem.php';
		//	this.filePathDeleteItem = 'folderTree_updateItem.php';
		this.ajaxObjects = new Array();
		this.helpObj = false;
		
		this.RENAME_STATE_BEGIN = 1;
		this.RENAME_STATE_CANCELED = 2;
		this.RENAME_STATE_REQUEST_SENDED = 3;
		this.renameState = null;
	}
	
	
	/* JSDragDropTree class */
	JSDragDropTree.prototype = {
		// {{{ addEvent()
	    /**
	     *
	     *  This function adds an event listener to an element on the page.
	     *
	     *	@param Object whichObject = Reference to HTML element(Which object to assigne the event)
	     *	@param String eventType = Which type of event, example "mousemove" or "mouseup"
	     *	@param functionName = Name of function to execute. 
	     * 
	     * @public
	     */	
		addEvent : function(whichObject,eventType,functionName)
		{ 
		  if(whichObject.attachEvent){ 
		    whichObject['e'+eventType+functionName] = functionName; 
		    whichObject[eventType+functionName] = function(){
				    	whichObject['e'+eventType+functionName]( window.event );
				    } 
		    whichObject.attachEvent( 'on'+eventType, whichObject[eventType+functionName] ); 
		  } else 
		    whichObject.addEventListener(eventType,functionName,false); 	    
		} 
		// }}}	
		,	
		// {{{ removeEvent()
	    /**
	     *
	     *  This function removes an event listener from an element on the page.
	     *
	     *	@param Object whichObject = Reference to HTML element(Which object to assigne the event)
	     *	@param String eventType = Which type of event, example "mousemove" or "mouseup"
	     *	@param functionName = Name of function to execute. 
	     * 
	     * @public
	     */		
		removeEvent : function(whichObject, eventType, functionName)
		{ 
		  if(whichObject.detachEvent){ 
		    whichObject.detachEvent('on'+eventType, whichObject[eventType+functionName]); 
		    whichObject[eventType+functionName] = null; 
		  } else 
		    whichObject.removeEventListener(eventType,functionName,false); 
		} 
		,	
		Get_Cookie : function(name) { 
		   var start = document.cookie.indexOf(name+"="); 
		   var len = start+name.length+1; 
		   if ((!start) && (name != document.cookie.substring(0,name.length))) return null; 
		   if (start == -1) return null; 
		   var end = document.cookie.indexOf(";",len); 
		   if (end == -1) end = document.cookie.length; 
		   return unescape(document.cookie.substring(len,end)); 
		} 
		,
		// This function has been slightly modified
		Set_Cookie : function(name,value,expires,path,domain,secure) { 
			expires = expires * 60*60*24*1000;
			var today = new Date();
			var expires_date = new Date( today.getTime() + (expires) );
		    var cookieString = name + "=" +escape(value) + 
		       ( (expires) ? ";expires=" + expires_date.toGMTString() : "") + 
		       ( (path) ? ";path=" + path : "") + 
		       ( (domain) ? ";domain=" + domain : "") + 
		       ( (secure) ? ";secure" : ""); 
		    document.cookie = cookieString; 
		} 
		,
		setAdditionalRenameRequestParameters : function(requestParameters)
		{
			this.additionalRenameRequestParameters = requestParameters;
		}
		,
		setAdditionalDeleteRequestParameters : function(requestParameters)
		{
			this.additionalDeleteRequestParameters = requestParameters;
		}
		
		,setMaximumDepth : function(maxDepth)
		{
			this.maximumDepth = maxDepth;	
		}
		,setMessageMaximumDepthReached : function(newMessage)
		{
			this.messageMaximumDepthReached = newMessage;
		}
		,	
		setImageFolder : function(path)
		{
			this.imageFolder = path;	
		}
		,
		setFolderImage : function(imagePath)
		{
			this.folderImage = imagePath;			
		}
		,		
		setTreeId : function(idOfTree)
		{
			this.idOfTree = idOfTree;			
		}	
		,
		//** Find top pos of a tree node
		getTopPos : function(obj){
			var top = obj.offsetTop/1;
			while((obj = obj.offsetParent) != null){
				if(obj.tagName!='HTML')top += obj.offsetTop;
			}			
			if(document.all)top = top/1 + 13; else top = top/1 + 4;		
			return top;
		}
		,	
		// ** Find left pos of a tree node
		getLeftPos : function(obj){
			var left = obj.offsetLeft/1 + 1;
			while((obj = obj.offsetParent) != null){
				if(obj.tagName!='HTML')left += obj.offsetLeft;
			}
	  			
			if(document.all)left = left/1 - 2;
			return left;
		}	
		
		,
		dragDropCountLevels : function(obj,direction,stopAtObject){
			var maxLevel = 0;
			var objDepth = 0;
		    if(obj.getElementsByTagName('SPAN').length>0) {
		    	var subNodes = obj.getElementsByTagName('SPAN');
		    	for(var no=0;no<subNodes.length;no++){
		    		if(subNodes[no].id.indexOf('SPAN')==-1)
		    			continue;
		    		var currentLevel = subNodes[no].getAttribute('level');
		    		if(currentLevel > maxLevel)
						maxLevel = currentLevel;
				}
				
				var objLevel = obj.getAttribute('level');
		    	objDepth = maxLevel-objLevel;
		    }
		   
			return objDepth;
			
		}		
		,
		cancelEvent : function()
		{
			return false;	
		}
		,
		cancelSelectionEvent : function()
		{
			
			if(JSTreeObj.dragDropTimer<10)return true;
			return false;	
		}
		,
		getNodeOrders : function(initObj,saveString)
		{
			
			if(!saveString)var saveString = '';
			if(!initObj){
				initObj = document.getElementById(this.idOfTree);

			}
			var lis = initObj.getElementsByTagName('LI');

			if(lis.length>0){
				var li = lis[0];
				while(li){
					if(li.id){
						if(saveString.length>0)saveString = saveString + ',';
						var numericID = li.id.replace(/[^0-9]/gi,'');
						if(numericID.length==0)numericID='A';
						var numericParentID = li.parentNode.parentNode.id.replace(/[^0-9]/gi,'');
						if(numericID!='0'){
							saveString = saveString + numericID;
							saveString = saveString + '-';
							
							
							if(li.parentNode.id!=this.idOfTree)saveString = saveString + numericParentID; else saveString = saveString + '0';
						}
						var ul = li.getElementsByTagName('UL');
						if(ul.length>0){
							saveString = this.getNodeOrders(ul[0],saveString);	
						}	
					}			
					li = li.nextSibling;
				}
			}

			if(initObj.id == this.idOfTree){
				return saveString;
							
			}
			return saveString;
		}
		
		,highlightItem : function(inputObj,e)
		{
			if(JSTreeObj.currentlyActiveItem)
				JSTreeObj.currentlyActiveItem.className = '';
			this.className = 'highlightedNodeItem';
			JSTreeObj.currentlyActiveItem = this;
		}
		,
		removeHighlight : function()
		{
			if(JSTreeObj.currentlyActiveItem)JSTreeObj.currentlyActiveItem.className = '';
			JSTreeObj.currentlyActiveItem = false;
		}
		,
		hasSubNodes : function(obj)
		{
			var subs = obj.getElementsByTagName('SPAN');
			if(subs.length>0)return true;
			return false;	
		}
		,
		__refreshDisplay : function(obj)
		{
			if(this.hasSubNodes(obj))return;

			var img = obj.getElementsByTagName('IMG')[0];
			img.style.visibility = 'hidden';	
		}

		,
		createDropIndicator : function()
		{
			this.dropTargetIndicator = document.createElement('DIV');
			this.dropTargetIndicator.style.position = 'absolute';
			this.dropTargetIndicator.style.display='none';			
			var img = document.createElement('IMG');
			img.src = this.imageFolder + 'dragDrop_ind1.gif';
			img.id = 'dragDropIndicatorImage';
			this.dropTargetIndicator.appendChild(img);
			document.body.appendChild(this.dropTargetIndicator);
			
		}
		,
		initTree : function()
		{
			JSTreeObj = this;
			JSTreeObj.createDropIndicator();
			document.documentElement.onselectstart = JSTreeObj.cancelSelectionEvent;
			document.documentElement.ondragstart = JSTreeObj.cancelEvent;
			document.documentElement.onmousedown = JSTreeObj.removeHighlight;
			//** Creating help object for storage of values:
			/*this.helpObj = document.createElement('DIV');
			this.helpObj.style.display = 'none';
			document.body.appendChild(this.helpObj);
			*/
			var theTreeMenu = $('#'+this.idOfTree);
			$('span[@id^=SPAN]', theTreeMenu).each(
				function()
				{
					CurrSpanId = this.id;
					CurrSpan = this;
					$('a',CurrSpan).get(0).id = CurrSpanId.replace("SPAN","LINK");
					//$('a',CurrSpan).get(0).onmousedown = JSTreeObj.initDrag;
					$('a',CurrSpan).get(0).onmousemove = JSTreeObj.moveDragableNodes;

					var FoldIMGId = CurrSpanId.replace("SPAN","FOLDERIMG_");
					if($('#'+FoldIMGId).is("img"))
					{
						$('#'+FoldIMGId).css('cursor','move');
						$('#'+FoldIMGId).mousedown(JSTreeObj.initDrag);
						$('#'+FoldIMGId).mousemove(JSTreeObj.moveDragableNodes);
					}
				}
			);
			
			theTreeMenu.mousemove(JSTreeObj.moveDragableNodes);
			theTreeMenu.mouseup(JSTreeObj.dropDragableNodes);
		}
		
		,
		/* Initialize drag */
		initDrag : function(e)
		{
			if(document.all)  e = event;	
			
			if(this.id.indexOf('IMAGE')!=-1)
				sourceId = this.id.replace('IMAGE','SPAN');
			else if(this.id.indexOf('FOLDERIMG_')!=-1)
				sourceId = this.id.replace('FOLDERIMG_','SPAN');
			else if(this.id.indexOf('LINK')!=-1)
				sourceId = this.id.replace('LINK','SPAN');
				
			JSTreeObj.dragNode_source = document.getElementById(sourceId);
			JSTreeObj.dragNode_parent = JSTreeObj.dragNode_source.parentNode;
			JSTreeObj.dragNode_sourceNextSib = false;
			
			//** Frère suivant du noeud en cours:
			if(JSTreeObj.dragNode_source.nextSibling){
				
				if(JSTreeObj.dragNode_source.nextSibling.tagName=='SPAN') {
					JSTreeObj.dragNode_sourceNextSib = JSTreeObj.dragNode_source.nextSibling ;
					if(JSTreeObj.dragNode_sourceNextSib.id.indexOf('BigNode')!=-1){
						JSTreeObj.dragNode_source.appendChild(JSTreeObj.dragNode_sourceNextSib);
						if(JSTreeObj.dragNode_sourceNextSib.nextSibling){
							JSTreeObj.dragNode_sourceNextSib = JSTreeObj.dragNode_sourceNextSib.nextSibling;
						}
					}
					else if(JSTreeObj.dragNode_sourceNextSib.id.indexOf('SPAN')!=-1){
							JSTreeObj.dragNode_sourceNextSib = JSTreeObj.dragNode_sourceNextSib.nextSibling;
					}
				}
			}

			JSTreeObj.dragNode_destination = false;
			JSTreeObj.dragDropTimer = 0;
			JSTreeObj.timerDrag();
			return false;
		}
		
		,
		timerDrag : function()
		{	
			if(this.dragDropTimer>=0 && this.dragDropTimer<10){
				this.dragDropTimer = this.dragDropTimer + 1;
				setTimeout('JSTreeObj.timerDrag()',20);
				return;
			}
			if(this.dragDropTimer==10)
			{
				JSTreeObj.floatingContainer.style.display='block';
				JSTreeObj.floatingContainer.appendChild(JSTreeObj.dragNode_source);	
				JSTreeObj.floatingContainer.style.opacity=0.4;
			}
		}
		,
		moveDragableNodes : function(e)
		{
			if(JSTreeObj.dragDropTimer<10) return;
			
			if(document.all)	e = event;
			dragDrop_x = e.clientX/1 + 5 + document.body.scrollLeft;
			dragDrop_y = e.clientY/1 + 5 + document.documentElement.scrollTop;	
					
			JSTreeObj.floatingContainer.style.left = dragDrop_x +'px';
			JSTreeObj.floatingContainer.style.top  = dragDrop_y +'px';
			
			var thisObj = this;
			while(thisObj.tagName!='SPAN' && thisObj.parentNode!=null){
				if(!thisObj.id){
					thisObj = thisObj.parentNode ;
				}
				else if(thisObj.id.indexOf('SPAN')==-1){
					thisObj = thisObj.parentNode ;
				}
			}
			
			if(thisObj && thisObj.id)
			{	
				if(thisObj.id.indexOf('SPAN')==-1){
					
					JSTreeObj.dragNode_destination = false;
					return;
				}
				else {
					JSTreeObj.dragNode_noSiblings = false;
					JSTreeObj.dragNode_destination = thisObj;
				}
				
				var eventSourceObj = this;
				if(JSTreeObj.dragNode_noSiblings && eventSourceObj.tagName=='IMG' && eventSourceObj.nextSibling)
					eventSourceObj = eventSourceObj.nextSibling;
					
				//** style pour l'indicateur tmpObj qui contient tmpImg(flèche):
				var tmpObj = JSTreeObj.dropTargetIndicator;
				tmpObj.style.display = 'block';
				var tmpImg = tmpObj.getElementsByTagName('IMG')[0];
				
				if(document.all){
					X = 2;	X_sub = 4;	YImg = 14 ; YLink = 2;
				}
				else{
					X = 2;	X_sub = 2;	YImg = 8; YLink = 8;			
				}
				if(navigator.userAgent.indexOf('Opera')>=0){
					X = 2;	X_sub = 3;  Y = -7;				
				}
				
				if(this.tagName=='A'){
					tmpImg.src = tmpImg.src.replace('ind1','ind2');	
					JSTreeObj.insertAsSub = true;
					tmpObj.style.left = (JSTreeObj.getLeftPos(eventSourceObj) + JSTreeObj.indicator_offsetX_sub+2) + 'px';
					tmpObj.style.top = (JSTreeObj.getTopPos(thisObj) + JSTreeObj.indicator_offsetY + YLink) + 'px';
				}
				else{
					tmpImg.src = tmpImg.src.replace('ind2','ind1');
					JSTreeObj.insertAsSub = false;
					tmpObj.style.left = (JSTreeObj.getLeftPos(eventSourceObj) + JSTreeObj.indicator_offsetX-2) + 'px';
					tmpObj.style.top = (JSTreeObj.getTopPos(thisObj) + JSTreeObj.indicator_offsetY - YImg) + 'px';
				}
			}
			return false;
		}
		,
		
		dropDragableNodes:function()
		{
			if(JSTreeObj.dragDropTimer<10){
				JSTreeObj.dragDropTimer = -1;
				return;
			}
			var showMessage = false ;
			//** Test sur non dépassement de la profondeur max du tree:
			if(JSTreeObj.dragNode_destination){	// Check depth
			
				//var countUp = JSTreeObj.dragDropCountLevels(JSTreeObj.dragNode_destination,'up');
				var countUp = JSTreeObj.dragNode_destination.getAttribute('level');
				var countDown = JSTreeObj.dragDropCountLevels(JSTreeObj.dragNode_source,'down');
				var countLevels = countUp/1 + countDown/1 + (JSTreeObj.insertAsSub?1:0);
				
				if(countLevels>JSTreeObj.maximumDepth){
					JSTreeObj.dragNode_destination = false;
					showMessage = true; 	// Used later down in this function
				}
			
			}
			
			JSTreeObj.dropTargetIndicator.style.display='none';
			JSTreeObj.dragDropTimer = -1;
			
			if(JSTreeObj.dragNode_destination){	
				if(JSTreeObj.insertAsSub){
					if(document.getElementById(JSTreeObj.dragNode_destination.id.replace('SPAN','BigNode'))!=null){
						
						destBigNode = document.getElementById(JSTreeObj.dragNode_destination.id.replace('SPAN','BigNode')); 
						destBigNode.appendChild(JSTreeObj.dragNode_source);
					}
					else{
						var destBigNode = document.createElement('SPAN');
						destBigNode.id = JSTreeObj.dragNode_destination.id.replace('SPAN','BigNode');
						destBigNode.appendChild(JSTreeObj.dragNode_source);
						
						if (JSTreeObj.dragNode_destination.nextSibling) {
							JSTreeObj.dragNode_destination.parentNode.insertBefore(destBigNode, JSTreeObj.dragNode_destination.nextSibling);
						}
						else{
							JSTreeObj.dragNode_destination.parentNode.appendChild(destBigNode);
						}
					}
					//** Changement de la variable cookie(Noeuds ouverts):
					var openNode = LireCookie('OpenNode');
						openNode += ','+destBigNode.id ;
						EcrireCookie("OpenNode", openNode);
						
					SQ_FormGeneric(Data,'Event','DragAndDropOnTree','_SQ','Y',
										  'SourceNodeId', JSTreeObj.dragNode_source.id,
										  'DestNodeId', JSTreeObj.dragNode_destination.id,
										  'InsertAsSub', 'Y',
										  'AjaxFunction','setNewTreeView');
				}
				else{
					if(JSTreeObj.dragNode_destination.parentNode){
							JSTreeObj.dragNode_destination.parentNode.insertBefore(JSTreeObj.dragNode_source,JSTreeObj.dragNode_destination);
					}	
					SQ_FormGeneric(Data, 'Event','DragAndDropOnTree','_SQ','Y',
										 'SourceNodeId', JSTreeObj.dragNode_source.id,
										 'DestNodeId', JSTreeObj.dragNode_destination.id,
										 'InsertAsSub', 'N',
										 'AjaxFunction','setNewTreeView');
				}
			}
			else{
				if (JSTreeObj.dragNode_source.nextSibling) {
					JSTreeObj.dragNode_parent.insertBefore(JSTreeObj.dragNode_source, JSTreeObj.JSTreeObj.dragNode_source.nextSibling);
				}
				else{
					JSTreeObj.dragNode_parent.appendChild(JSTreeObj.dragNode_source);
				}
				SQ_FormGeneric(Data,'Event','DragAndDropOnTree','_SQ','Y',
										    'SourceNodeId', JSTreeObj.dragNode_source.id,
										    'DestNodeId', JSTreeObj.dragNode_source.id,
										    'AjaxFunction','setNewTreeView');			
			
			}
		
			if(showMessage && JSTreeObj.messageMaximumDepthReached){
				alert(JSTreeObj.messageMaximumDepthReached);
			}
			
			//** Réinitialisation du TreeView:
			JSTreeObj.initTree();
		}
		
		
	}
