/**
 * foxxworxx javascript framework
 * @version 0.2.15.270207 BETA
 * @author Markus Engel <me@foxxworxx.com>
 * @copyright Copyright (c) 2007 Markus Engel
 * @link http://www.foxxworxx.com
 * @license http://www.foxxworxx.com/licenses
 */


var FWF =
{
	isIE : (navigator.appName.indexOf('Microsoft') != -1)? true : false
}; // FWF Objekt

/**
 * hilfreiche tools
 */
FWF.util =
{
	isArray : function(obj)
	{
  	if(!FWF.util.isUndefined(obj) && obj.constructor && obj.constructor.toString().indexOf('Array') > -1)
  	{
    	return true;
    }
    else
    {
      return FWF.util.isObject(obj) && obj.constructor == Array;
    }
	}, // isArray

  isBoolean : function(obj)
  {
  	return typeof obj == 'boolean';
  }, // isBoolean 
	
	isFunction : function(obj)
	{
		return typeof obj == 'function';
	}, // isFunction

  isNull : function(obj)
  {
		return obj === null;
  }, // isNull

  isNumber : function(obj)
  {
  	return typeof obj == 'number' && isFinite(obj);
  }, // isNumber
	
	isObject : function(obj)
	{
		return typeof obj == 'object' || FWF.util.isFunction(obj);
	}, // isObject
	
  isString : function(obj)
  {
		return typeof obj == 'string';
  }, // isString
  
  isUndefined : function(obj)
  {
		return typeof obj == 'undefined';
  } // isUndefined 
} // FWF.util objekt

/**
 * elemente
 */
FWF.element = 
{	
	/**
	 * @method create
	 * @param string elm welches element soll erzeugt werden (div, a, p, ...)
	 * @param object parentObj objekt welches das neue element dazugefügt wird
	 * @param string attr attribute für das neue element, mehrere durch ',' getrennt, hat nicht mit style zutun, sondern mit id name... des elementes
	 * @param string val wert des attributes, mehrerer dur ',' getrennt
	 * @treturn object objekt des erstellten elementes
	 */
	create : function(elm, parentObj, attr, val)
	{
		var crElm =  document.createElement(elm);
		
		if(attr && val)
		{
			var a = attr.replace(/, /g, ',').split(',');
			var v = val.replace(/, /g, ',').split(',');
		
			if(a.length == v.length)
			{
				for(var i = 0; i < a.length; i++)
				{
					crElm.setAttribute(a[i], v[i]);
				}
			}
		}
		
		if(FWF.util.isObject(parentObj)) parentObj.appendChild(crElm);
		
		return crElm;	
	}, // create

	/**
	 * @method get
	 * @param string id id, name oder tagname des elementes
	 * @param string w werte id|null, name und tag
	 * @return object objekt des elementes
	 */
	get : function(id, w)
	{
		if(!w) w = 'id';
		
		switch(w)
		{
			case 'id':
				return document.getElementById(id);
			break;
			
			case 'name':
				return document.getElementsByName(id);
			break;
			
			case 'tag':
				return document.getElementsByTagName(id);
			break;
		}	
	}, // get

	/**
	 * @method getFromEvent
	 * @param object evt event übergabe (bei ist es null)!
	 * @param string id id des gesuchten elementes
	 * @return object objekt des elementes
	 */
	getFromEvent: function(evt, id)
	{
		var obj = null;
		
		if(FWF.isIE)
		{
			obj = window.event;
			obj.cancelBubble = true;
			obj = obj.srcElement;
			
			while(obj.id.indexOf(id) == -1)
			{
				obj = obj.parentNode;
			}
		}
		else
		{
			obj = evt;
			obj.stopPropagation();
			obj = obj.currentTarget;
		}
		
		return obj;
	}, // getFromEvent
	
	/**
	 * @method remove
	 * @param object elmObj das element objekt das entfernt werden soll
	 * @param object parentObj das element objekt wo das element entfernt werden soll
	 */
	remove : function(elmObj, parentObj)
	{
		if(FWF.util.isObject(parentObj) && FWF.util.isObject(elmObj)) parentObj.removeChild(elmObj);	
	}, // remove
	
	/**
	 * OBJECT SECTION von elemente
	 */
	
	/**
	 * @object class
	 */
	cssClass :
	{
		/**
		 * @method add
		 * @param mixed id id oder elementObjekt des elementes
		 * @param string cls css-klassenname der zugefügt werden soll
		 */		
		add : function(id, cls)
		{
			if(this.has(id, cls)) return ;
			
			var obj = !FWF.util.isObject(id)? FWF.element.get(id) : id;
			
			obj.className += ' '+ cls;
		}, // add

		/**
		 * @method hs
		 * @param mixed id id oder elementObjekt des elementes
		 * @param string cls css-klassenname der überpfrüft werden soll
		 * @return boolean
		 */		
		has : function(id, cls)
		{
			var obj = !FWF.util.isObject(id)? FWF.element.get(id) : id;
			
			return (obj.className && obj.className.indexOf(cls) != -1)? true : false;
		}, // has
		
		/**
		 * @method remove
		 * @param mixed id id oder elementObjekt des elementes
		 * @param string cls css-klassenname der enfert werden soll
		 */
		remove : function(id, cls)
		{
			var obj = !FWF.util.isObject(id)? FWF.element.get(id) : id;
			var clsA = obj.className.indexOf(' ') != -1? obj.className.split(' ') : Array(obj.className);
			var clsB = '';
			
			for(var i = 0; i < clsA.length; i++)
			{
				if(clsA[i] != cls) clsB += ' '+ clsA[i];
			}
			
			obj.className = clsB;
		}, // remove
		
		/**
		 * @method replace
		 * @info wrapper für remove und dann gleich add
		 * @param mixed id id oder elementObjekt des elementes
		 * @param string rCls css-klassenname die ersetz werden soll
		 * @param string nCls css-klassenname der neuen klasse
		 */
		replace : function(id, rCls, nCls)
		{
			if(!this.has(id, rCls)) return;
			
			this.remove(id, rCls);
			this.add(id, nCls);	
		} // replace
	}, // object class
	
	/**
	 * @object listener
	 */
	listener :
	{
		/**
		 * @method add
		 * @param mixed id id oder elementObjekt des elementes
		 * @param string type welcher event soll dazugefügt werden (click, move, mousedown...)
		 * @param function cb callback function
		 */
		add : function(id, type, cb)
		{
			var obj = !FWF.util.isObject(id)? FWF.element.get(id) : id;
			
		   if(obj.addEventListener)
		   {
		      obj.addEventListener(type, cb, false);
		   }
		   else if(obj.attachEvent)
		   {
		   		obj.attachEvent('on'+ type, cb);
		   }
		}, // add
		
		/**
		 * @method remove
		 * @param mixed id id oder elementObjekt des elementes
		 * @param string type welcher event soll entfernt werden (click, move, mousedown...)
		 * @param function cb callback function
		 */		 
		remove : function(id, type, cb)
		{
			var obj = !FWF.util.isObject(id)? FWF.element.get(id) : id;
			
		  if(obj.removeEventListener)
		  {
		     obj.removeEventListener(type, cb, false);
		  }
		  else if(obj.detachEvent)
		  {
		     obj.detachEvent('on'+ type, cb);
		  }
		}	// remove
	}, // object listener

	/**
	 * @object style
	 */
	style :
	{
		/**
		 * @method get
		 * @param mixed id id oder elementObjekt des elementes
		 * @param string attr das attribute das ausgelesen werden soll, mehrere attr durch ',' trennen
		 * @return object attribute = value
		 */
		get : function(id, attr)
		{
			var obj = !FWF.util.isObject(id)? FWF.element.get(id) : id;
			
			var o = new Object();
			
			attr = attr.replace(/, /g, ',').split(',');
			
			for(var i = 0; i < attr.length; i++)
			{
				o[attr[i]] = obj.style[attr[i]];
			}
			
			return o;
			
		}, // get
		
		/**
		 * @method set
		 * @param mixed id die id oder das elementObjekt das bearbeitet werden soll, kann auch via array übergeben werden
		 * @param mixed attr die style attribute (width, position... {cssText}) mehrere attr durch ',' trennen, auch via array möglich, ist id ein array und attr ein array, dann müssen sie gleichviele element haben, da soinst nur das erste genommen wird für alle
		 * @param mixed val die werte für die atribute, weitere möglichkeiten wie attr
		 */
		set : function(id, attr, val)
		{
			var a, v;
			
			var loop = !FWF.util.isArray(id)? Array(id) : id;
			
			attr = !FWF.util.isArray(attr)? Array(attr.toString()) : attr;
			val = !FWF.util.isArray(val)? Array(val.toString()) : val;
			
			for(var x = 0; x < loop.length; x++)
			{
				var obj = FWF.util.isObject(loop[x])? loop[x] : FWF.element.get(loop[x]);
				
				if(FWF.util.isArray(attr) && attr.length == loop.length && FWF.util.isArray(val) && val.length == loop.length)
				{
					a = attr[x].replace(/, /g, ',').split(',');
					v = val[x].replace(/, /g, ',').split(',');
				}
				else if(!FWF.util.isArray(a) && !FWF.util.isArray(v))
				{
					a = attr[0].replace(/, /g, ',').split(',');
					v = val[0].replace(/, /g, ',').split(',');
				}
				
				if(a.length == v.length)
				{
					for(var i = 0; i < a.length; i++)
					{
						obj.style[a[i]] = v[i];
					}
				}
			}
				
		} // set
	}, // object style
	
	/**
	 * @object XY
	 */
	xy :
	{	
		/**
		 * @method get
		 * @param mixed id die id oder elementObjekt des elementes
		 * @return array mit den beiten werden (x,y)
		 */
		get : function(id)
		{
			var obj = !FWF.util.isObject(id)? FWF.element.get(id) : id;
			var val = Array(obj.offsetTop, obj.offsetLeft);
			
			if(obj.offsetParent)
			{
				while(obj.offsetParent)
				{
					obj = obj.offsetParent;
					
					val[0] += obj.offsetTop;
					val[1] += obj.offsetLeft;
				}
			}
			
			return val;
		}, // get
		
		/**
		 * @method set
		 * @info wrapper für FWF.element.style.set(obj, 'top, left', '...')
		 * @param mixed id die id oder elementObjekt des elementes
		 * @param array pos ein array der xy kord.
		 */
		set : function(id, pos)
		{
			var obj = !FWF.util.isObject(id)? FWF.element.get(id) : id;
			if(!FWF.util.isArray(pos)) return false;
			
			FWF.element.style.set(obj, 'top, left', pos[0] +', '+ pos[1]);
		} // set
	}, // object xy
	
	/**
	 * @object opacity
	 */
	opacity :
	{
		step : 1, // opaticy sprünge 
		speed : 20, // millisek. zwischen den sprüngen
		dir : 'in', // in welche richtung soll das alpha blending eingesetzt werden
										 // out = 100 -> 0, ausblenden
										 // in = 0 -> 100, einblenden
									
		cb : null, // funktion die aufgerufen werden soll wenn anim fertig ist
		obj : Object(), //
		
		animate : function(animID)
		{
			var run = true;
			var speed = this.obj[animID].speed;
			var dir = this.obj[animID].dir;
			var step = this.obj[animID].step;
			var cb = this.obj[animID].cb;
			var obj = this.obj[animID].elm;
			var opa = FWF.isIE? parseInt(obj.style.filter.replace(')', '').split('=')[1]) : obj.style.opacity;
			if(isNaN(opa)) opa = (this.dir == 0)? 100 : parseInt(0);
			
			
			if(FWF.isIE)
			{
				if(dir == 'out')
				{
					opa -= step;
					if(opa < 0 )
					{
						run = false;
						opa = 0;
					}
				}
				else
				{
					opa += step;
					if(opa > 100)
					{
						run = false;
						opa = 100;
					}
				}
				obj.style.filter = 'Alpha(opacity='+ opa +')';	
			}
			else
			{
				if(dir == 'out')
				{
					opa -= step / 100;
					if(opa < 0 )
					{
						run = false;
						opa = 0;
					}
				}
				else
				{
					opa -= -(step / 100);
					if(opa > 1)
					{
						run = false;
						opa = 1;
					}
				}
				obj.style.opacity = opa;				
			}
			
			if(run)
			{
				window.setTimeout('FWF.element.opacity.animate("'+ animID +'")', speed);
			}
			else if(cb)
			{
				cb();
				delete this.obj[animID];
			}				
		}, // animate
		
		/**
		 * @method anim
		 * @param mixed id die id oder elementObjekt des elementes
		 * @param int speed geschwindigkeit der animation in millisekunden
		 * @param string dir in welche richtung solls gehen, in = einblenden, out = ausblenden
		 * @param int step opactiy sprünge
		 * @param function cb callback function wenn die animation fertig ist
		 */
		anim : function(id, dir, speed, step, cb)
		{			
			var obj = new Object();
			
			obj.elm = !FWF.util.isObject(id)? FWF.element.get(id) : id;
			obj.speed = (speed)? speed : this.speed;
			obj.dir = (dir && dir == 'out' || dir == 'in')? dir : this.dir;
			obj.step = (step)? step : this.step;
			obj.cb = (cb)? cb : this.cb;
			
			this.obj[obj.elm.id] = obj;
			
			if(id) this.animate(obj.elm.id);
		}, // anim

		/**
		 * @method get
		 * @param mixed id die id oder elementObjekt des elementes
		 */
		get: function(id)
		{
			if(FWF.isIE)
			{
				return parseInt(FWF.element.style.get(id, 'filter').filter.replace(')', '').split('=')[1]);
			}
			else
			{
				return FWF.element.style.get(id, 'opacity').opacity * 100;
			}		
		}, // get
		
		/**
		 * @method set
		 * @param mixed id die id oder elementObjekt des elementes
		 * @param int opa alpha wert (0 - 100)
		 */
		set: function(id, opa)
		{
			if(FWF.isIE)
			{
				FWF.element.style.set(id, 'filter', 'Alpha(opacity='+ opa +')');
			}
			else
			{
				FWF.element.style.set(id, 'opacity', (opa / 100));
			}		
		} // set
	} // object opacity

} // FWF.element objekt
