// <script>
"use strict";
// return wether two divs intersect
function intersect(div1, div2)
{
	var d1=div1.cumulativeOffset();
	var d2=div2.cumulativeOffset();
	var a={"left":d1.left,"right":d1.left+div1.width(),"top":d1.top,"bottom":d1.top+div1.height()};
	var b={"left":d2.left,"right":d2.left+div2.width(),"top":d2.top,"bottom":d2.top+div2.height()};
	return (	a.left <= b.right &&
				b.left <= a.right &&
				a.top <= b.bottom &&
				b.top <= a.bottom
			)
}
//return wether pt is in div
function ptInRect(pt,div)
{
	var d1=div.cumulativeOffset();
	var dRight=d1.left+div.getWidth();
	var dBottom=d1.top+div.getHeight();
	return(	pt.left >= d1.left &&
			pt.left <= dRight &&
			pt.top >= d1.top &&
			pt.top <= dBottom
			)
}
// return widget whose pt is in. Null if none
function ptInWidget(pt)
{
	var rslt=null;
	var z=0;
	widgets.each( function(w,x)
					{
						if(ptInRect(pt,w.value.widgetStruct)&& w.value.widgetStruct.style.zIndex>z)
						{
							rslt=w.value;z=w.value.widgetStruct.style.zIndex;
						}
					}
				)
	return(rslt);
}
//collection of droppables (custom drag and drop. cf "initdrag")
var droppables=new Hash();

//Methods

Element.addMethods('DIV',
{
	//================== make element "droppable" cad enable to receive "draggables"
	//					input : action [start, stop, state
	droppable:function(element,action,initialValue,callBack)
	{
		element=$(element);
		if(!element || element.id=="") return(element);
		callBack=Object.isFunction(callBack)?callBack:null;
		if(action=="start")
		{
			droppables.set(element.id,{"element":element,"state":"","callBack":callBack});
		}
		else
		if(action=="stop")
			droppables.unset(element.id,element);
		else
		if(action=="state")
		{
			var d=droppables.get(element.id)
			if(d)
				d.state=initialValue;
		}
		return element;
	},
	
	//============================================= Make element draggable initialize events =========================================
	//options={"dragEnabled":"true","dragAndDrop":false,"dragCallback":"null","minx":"0","miny":"0","maxx":"0","maxy":"0"}
	initDrag:function(element,dTarget,options)
	{
		element=$(element);if(!element)return(element);
		var defaultoptions={	"dragEnabled":"true",
								"dragAndDrop":false,
								"dragCallback":"null",
								"minx":"0","miny":"0",
								"maxx":"0","maxy":"0"};
		element.dragOptions=Object.extend(defaultoptions,options);
		element.dragTarget = dTarget;
		element.mx = 0;
		element.my = 0;
		element.setStyle({"cursor":"move"});
		element.mmove=function(evt)
					{
							var  dx, dy;
							dx = evt.pageX - this.mx;
							dy = evt.pageY - this.my;
							this.mx = evt.pageX;
							this.my = evt.pageY;
							this.newLeft=this.dragTarget.left()+dx;
							if((Object.isNumber(this.dragOptions.minx)) && (this.newLeft<this.dragOptions.minx))this.newLeft=this.dragOptions.minx;
							if((Object.isNumber(this.dragOptions.maxx)) && (this.newLeft>this.dragOptions.maxx))this.newLeft=this.dragOptions.maxx;
							this.newTop=this.dragTarget.top()+dy;
							if((Object.isNumber(this.dragOptions.miny)) && (this.newTop<this.dragOptions.miny))this.newTop=this.dragOptions.miny;
							if((Object.isNumber(this.dragOptions.maxy)) && (this.newTop>this.dragOptions.maxy))this.newTop=this.dragOptions.maxy;
							if(this.newLeft<0)this.newLeft=0;
							if(this.newTop<0)this.newTop=0;
							this.dragTarget.left(this.newLeft);
							this.dragTarget.top(this.newTop);
							
							if(this.dragOptions.dragAndDrop)
							{
								droppables
								.each(function(e,x)
									{
										var el=e.value.element;
										if(intersect(el,this.dragTarget))
										{
											//console.log("state:"+e.value.state);
											if(e.value.state=="")
											{
												//console.log("enter");
												if(e.value.callBack){ e.value.callBack("enter"); }
												e.value.state="over";
											}
											else
											{
												e.value.state="over";
												if(e.value.callBack){ e.value.callBack("over"); }
											}
										}
										else
										{
											if(e.value.state=="over")
											{
												if(e.value.callBack){ e.value.callBack("out"); }
												e.value.state="";
											}
										}
									}.bind(this)
								 )
							}
							if(Object.isFunction(this.dragOptions.dragCallback))
								this.dragOptions.dragCallback(evt,this.newLeft,this.newTop,"moving");
						
					}.bindAsEventListener(element)
		element.mup=function(evt)
				{
								//evt.stop();
								document.stopObserving('mouseup',this.mup);
								document.stopObserving('mousemove',this.mmove);
								
							if(this.dragOptions.dragAndDrop)
							{
								droppables
								.each(function(e,x)
									{
										var el=e.value.element;
										if(intersect(el,this.dragTarget))
										{
											if(e.value.state=="over")
											{
												if(e.value.callBack){ e.value.callBack("drop",this); }
											}
											e.value.state="";
										}
									}.bind(this)
									)
							}
											
								if(Object.isFunction(this.dragOptions.dragCallback))
									this.dragOptions.dragCallback(evt,null,null,"endmoving");
								
				}.bindAsEventListener(element)

		element.observe('mousedown',
						function(evt)
					   {
							if (this.dragOptions.dragEnabled)
							{
								this.mx = evt.pageX;
								this.my = evt.pageY;
								document.stopObserving('mousemove',this.mmove);
								document.stopObserving('mouseup',this.mup);
								document.observe('mousemove',this.mmove);
								document.observe('mouseup',this.mup);
								if(Object.isFunction(this.dragOptions.dragCallback))
									this.dragOptions.dragCallback(evt,null,null,"startmoving");
							}
					   }.bindAsEventListener(element)
					   )
		return(element);
	},
	
	//============================================= Make element resizable initialize events =========================================
	initResize:function(hotResizeElement,resizeElement,callback)
	{
		
		hotResizeElement.resizeEnabled = true;
		hotResizeElement.resizeTarget=resizeElement;
		hotResizeElement.hotResizeElement=hotResizeElement;
		hotResizeElement.hotResizeElement.mx = 0;
		hotResizeElement.hotResizeElement.my = 0;
		hotResizeElement.callback = callback;
		hotResizeElement.gRot="";
		hotResizeElement.mmoveResize=function(evt)
								{
									var  dx, dy;
									var posHot=hotResizeElement.cumulativeOffset();
									var posDrag=resizeElement.cumulativeOffset();
									
									var newWidth=evt.pageX-posDrag.left+hotResizeElement.width()/2 ;
									var newHeight=evt.pageY-posDrag.top+hotResizeElement.height()/2 ;
									
									//console.log(newWidth+" "+newHeight);
									  if(newWidth<this.minWidth)newWidth=this.minWidth;
									  if(newHeight<this.minHeight)newHeight=this.minHeight;
									  if(newWidth>this.maxWidth)newWidth=this.maxWidth;
									  if(newHeight>this.maxHeight)newHeight=this.maxHeight;
									//console.log(newWidth+" "+newHeight);
									  resizeElement.resize(newWidth,newHeight);
									 // alert(this.callback);
									  if(this.callback)this.callback(newWidth,newHeight);
									  evt.stop();
									 }
			hotResizeElement.mmoveResizeHandler=hotResizeElement.mmoveResize.bind(hotResizeElement);
		
			$(hotResizeElement).observe('mousedown',function(evt)
							 {
								  if (this.resizeEnabled)
								  {
									  evt.stop();
									  this.hotResizeElement.mx = evt.pageX;
									  this.hotResizeElement.my = evt.pageY;
									  document.observe('mousemove',this.mmoveResizeHandler)
									  this.mupResize=document.observe('mouseup',function(evt)
																			{
																				evt.stop();
																				document.stopObserving('mouseup',this.mupResize);
																				document.stopObserving('mousemove',this.mmoveResizeHandler);
																			}.bind(this)
													   )
								  }
							 }.bind(hotResizeElement)
				 )
		return(hotResizeElement);
	}
}
)
String.prototype.getExtension = function()
{
  var l=this.lastIndexOf(".");
	  if(l>0)
	  {
		  return(this.substr(l))
	  }
	  else
		  return("");
}
Element.addMethods(
{
	help:function(element,text)
	{
		element=$(element);
		element.observe("mouseenter",function(evt){
			currentHelpObj=element
		})
		.observe("mouseleave",function(evt){currentHelpObj=null});
		element.setAttribute("help",text);
		return element;
	},
	gradient:function(element,gType,goptions,gradients) //d.gradient("linear","left",Array(Array(r,g,b,transp,%pos),Array(41,137,216,0.45,24),Array(),...)
	{
		var element = $(element);
		if(!Object.isArray(gradients))return;
		var grs="";
		gradients.each(function(g,x)
		{
			if(Object.isArray(g) && g.length>3)
			{
				var u=g.length>5?g[5]:"%";
				grs+=", rgba("+g[0]+","+g[1]+","+g[2]+","+g[3]+")"+g[4]+u
			}
		}.bind(this)
		)
		//goptions+=goptions==""?"":",";
		element.setStyle({"background":"-moz-"+gType+"-gradient( "+goptions +grs+")"});
		element.setStyle({"background":"-webkit-"+gType+"-gradient( "+goptions +grs+")"});
		element.setStyle({"background":"-o-"+gType+"-gradient( "+goptions +grs+")"});
		element.setStyle({"background":"-ms-"+gType+"-gradient( "+goptions +grs+")"});
		return(element);
	},
	getCompStyle:function(element, p, i)
	{
	  element = $(element);
	  var s, v = 'undefined', dv = document.defaultView;
	  if(dv && dv.getComputedStyle){
		s = dv.getComputedStyle(element,'');
		if (s) v = s.getPropertyValue(p);
	  }
	  else if(element.currentStyle) {
		v = element.currentStyle[p.camelize()];
	  }
	  else return null;
	  return i ? (parseInt(v) || 0) : v;
	},
	left:function (element, iX)
	{
		element = $(element);
		var css= ! Object.isUndefined(element.style);
		if(css && Object.isString(element.style.left))
		{
			if(Object.isNumber(iX)) element.style.left=iX+'px';
			else
			{
			  iX=parseInt(element.style.left);
			  if(isNaN(iX)) iX=element.getCompStyle('left',1);
			  if(isNaN(iX)) iX=0;
			}
		  }
		  else
		  if(css &&  ! Object.isUndefined(element.style.pixelLeft))
		  {
			if(Object.isNumber(iX)) element.style.pixelLeft=iX;
			else iX=element.style.pixelLeft;
		  }
		  return iX;
	},
	top:function (element, iX)
	{
		element = $(element);
		var css= ! Object.isUndefined(element.style);
		if(css && Object.isString(element.style.top))
		{
			if(Object.isNumber(iX)) element.style.top=iX+'px';
			else
			{
			  iX=parseInt(element.style.top);
			  if(isNaN(iX)) iX=element.getCompStyle('top',1);
			  if(isNaN(iX)) iX=0;
			}
		  }
		  else
		  if(css &&  ! Object.isUndefined(element.style.pixelTop))
		  {
			if(Object.isNumber(iX)) element.style.pixelTop=iX;
			else iX=element.style.pixelTop;
		  }
		  return iX;
	},
	width:function(element,w)
	{	
	
		var css, pl=0, pr=0, bl=0, br=0, gcs;
		element = $(element);
		if (Object.isNumber(w))
		{
		  if (w<0) w = 0;
		  else w=Math.round(w);
		}
		else w=-1;
		var css= ! Object.isUndefined(element.style);
		if(css &&  ! Object.isUndefined(element.offsetWidth) && Object.isString(element.style.width))
		{
		  if(w>=0) {
			if (document.compatMode=='CSS1Compat')
			{
			  //gcs = xGetComputedStyle;
			  var pl=element.getCompStyle('padding-left',1);
			  if (pl !== null)
			  {
				pr=element.getCompStyle('padding-right',1);
				bl=element.getCompStyle('border-left-width',1);
				br=element.getCompStyle('border-right-width',1);
			  }
			  // Should we try this as a last resort?
			  // At this point getComputedStyle and currentStyle do not exist.
			  else
			  if( ! Object.isUndefined(element.offsetWidth) &&  ! Object.isUndefined(element.style.width))
			  {
				element.style.width=w+'px';
				pl=element.offsetWidth-w;
			  }
			}
			w-=(pl+pr+bl+br);
			if(isNaN(w)||w<0) return;
			else element.style.width=w+'px';
		  }
		  w=element.offsetWidth;
		}
		return w;
	},
	height:function(element,h)
	{
	
		var css, pl=0, pr=0, bl=0, br=0, gcs;
		element = $(element);
		if (Object.isNumber(h))
		{
		  if (h<0) h = 0;
		  else h=Math.round(h);
		}
		else h=-1;
		var css= ! Object.isUndefined(element.style);
		if(css &&  ! Object.isUndefined(element.offsetHeight) && Object.isString(element.style.height))
		{
			if(h>=0) {
			  if ((document.compatMode=='CSS1Compat')||(document.compatMode=='BackCompat'))
			  {
				var pt=element.getCompStyle('padding-top',1);
				if (pt !== null) {
				  var pb=element.getCompStyle('padding-bottom',1);
				  var bt=element.getCompStyle('border-top-width',1);
				  var bb=element.getCompStyle('border-bottom-width',1);
				}
				// Should we try this as a last resort?
				// At this point getComputedStyle and currentStyle do not exist.
				else if( ! Object.isUndefined(element.offsetHeight)&& ! Object.isUndefined(element.style.height))
				{
				  element.style.height=h+'px';
				  pt=element.offsetHeight-h;
				}
				else
				pt=0;
			  }
			  else
				pt=0;
			  h-=(pt+pb+bt+bb);
			  if(isNaN(h)||h<0) return;
			  else element.style.height=h+'px';
			}
			h=element.getHeight();
			//h=element.offsetHeight;
		  }
		return h;
	  },
	  center:function(element)
	  {
		 element = $(element);
		 var p=element.up()|| document.viewport ;
		 var d={};
		 if(p!=document.body)
		 {
			 var d=p.getDimensions();
			 
		 }
		 else
		 {
			d.width=WindowWidth();
			d.height=WindowHeight();
		 }
			 
		element.move((d.width-element.getWidth())/2,(d.height-element.getHeight())/2);
		 return(element);
	  },
	  move:function(element,l,t)
	  {
		 element = $(element);
		 element.left(l);
		 element.top(t);
		 return(element);
	  },
	  resize:function(element,w,h)
	  {
		 element = $(element);
		 element.width(w);
		 element.height(h);
		 return(element);
	  },
	  setSelectable:function(element,setit)
	  {
		  if(!setit)
		  {
			  element.setStyle({"MozUserSelect":"none","KhtmlUserSelect":"none","WebkitUserSelect":"none","userSelect":"none"})
		  }
		  else
		  	element.setStyle({"MozUserSelect":"all","KhtmlUserSelect":"all","WebkitUserSelect":"all","userSelect":"all"})
		 return(element);
	  },
		addWheelEvent:function(element,callBack)
		{
		/* Initialization code. */
			element.mouseWheelCallback=callBack;
			if (element.addEventListener)
			{
				//element.addEventListener('DOMMouseScroll', element._mouseWheelCallback, false).bindAsEventListener(element);
				//element.addEventListener('mousewheel', element._mouseWheelCallback, false).bindAsEventListener(element);
				element.observe('DOMMouseScroll',element._mouseWheelCallback.bindAsEventListener(element));
				element.observe('mousewheel',element._mouseWheelCallback.bindAsEventListener(element));
			}
			element.onmousewheel= callBack;
			//if(obj==window)
			document.onmousewheel = null;
			if(window.DOMMouseScroll)
			window.addEventListener('DOMMouseScroll',
										function(evt)
											{
													if (evt.preventDefault)
															evt.preventDefault();
													if(evt.stop)
														evt.stop();
													evt.returnValue = false;
											}, false);
			window.addEventListener('mousewheel',function(evt){evt.stop()})
			return(element);
		},
		_mouseWheelCallback:function(element,event)
		{
			event.stop();
			var delta = 0;
			if (!event) event = window.event;
			if (event.wheelDelta)
			{
				delta = event.wheelDelta/120; 
				if (window.opera) delta = -delta;
			} else if (event.detail)
			{
				delta = -event.detail/3;
			}
			if(element.mouseWheelCallback)
				element.mouseWheelCallback(delta);
			else
			{	
				var liste=element;
				var listeHeight=liste.getHeight()-element.getOffsetParent().getHeight();
				var xt=liste.top()+(delta*24);
				if(xt>0)xt=0;
				if(xt<(-listeHeight))xt= -listeHeight;
				liste.style.top=xt+"px";
				if (event.preventDefault)
						event.preventDefault();
				event.returnValue = false;
				return(false);
			}
		},
	  
	  dim:function (e,opTarget,uTime,callback)
	  {
		  if (!(e=$(e))) return;
		  if (!e.readAttribute('optimeout')) e.writeAttribute("optimeout" , 10);
		  e.writeAttribute("opTarget" , opTarget);
		  e.writeAttribute("opTime" , uTime);
		  e.writeAttribute("opStop" , false);
		  e.writeAttribute("callbackDim" , callback);
		  
			
		  e.writeAttribute("opA" , opTarget-parseFloat(e.getOpacity()));
		  if (e.readAttribute("opLinear"))
				e.writeAttribute('opB' , 1/uTime);
		  else
			  e.writeAttribute('opB' , Math.PI / (2 * uTime)); // B = period
		  e.writeAttribute('opD' , e.getOpacity());
		  var d = new Date();
		  e.writeAttribute('opC',d.getTime());
		  if (!e.readAttribute("dimming")) e._xOpTo(e);
		  return(e);
	  },
	  _xOpTo:function (e)
	  {
		if (!(e=$(e))) return;
		var now, s, t, newY, newX;
		now = new Date();
		t = now.getTime() - e.readAttribute('opC');
		if (e.readAttribute('opStop'))
		  {
			  e.writeAttribute('dimming',false );
		  }
		else
		{
		  if (t < e.readAttribute('opTime'))
		  {
			  setTimeout(function(e)
								  {
									  e._xOpTo(e.readAttribute('id'));
								  }, e.readAttribute('optimeout')).bind(e)
				  
			  s = e.readAttribute('opB') * t;
			  if (!e.readAttribute('opLinear')) s = Math.sin(s);
		  //    if (e.slideLinear) s = e.B * t;
		  //    else s = Math.sin(e.B * t);
			  var newOp = parseFloat(e.readAttribute('opA')) * s + parseFloat(e.readAttribute('opD'));
			  e.setOpacity(newOp);
			  e.writeAttribute('dimming' ,true);
			}  
			else
			{
			  e.setOpacity(e.readAttribute('opTarget'));
			  e.writeAttribute('dimming' ,false);
			  if ( Object.isFunction(e.callbackDim)) e.callbackDim();
			}
		}
	  }
	  
}
)
