/* 
 * Dimi JS Base Framework: js
 * Dmitrij Sosnovsenko
 * biodiscus@web.de
 * 
 * last update: 2011-02-06
 */

(function(){
	
var 
	window= this,
	js= window.js= function(sel,type){
		return new js.core.init(sel,type);
	};
	
js.core= js.prototype= {
	tags: {'body':1,'head':1},
	
	init: function(sel,type){
		// html element id -> js('id')
		if(typeof sel == 'string' ){
			// if element is in the collection, than return this+
			var obj= js.obj[sel];// quickly
			if(obj && obj.elm){
				this.id= sel;
				this.elm= obj.elm;
				return this;
			}
			if(!type){
				if(js.core.tags[sel]){this.elm= document.getElementsByTagName(sel)[0]}
				else{this.elm= document.getElementById(sel)}
			}else{
				if(type == 'name'){
					this.elm= document.getElementsByName(sel);
				}else
				if(type == 'tag'){
					this.elm= document.getElementsByTagName(sel);
				}
				else
				if(type == 'html'){
					this.elm= js.dom.create(sel);
					this.id= js.obj.add(this.elm.id,this.elm);
					return this;
				}
			}
			
			this.id= js.obj.add(sel,this.elm);
			return this;
		}else
		// html object
		if(sel && sel.nodeType){
			this.elm= sel;
			if(sel == document){
				this.id= this.elm.id= 'document'
				js.obj.add('document',sel);
				return this;
			}
			this.id= js.obj.add(sel.id,sel);
			return this;
		}else
		if(sel == window){
			this.elm= sel;
			return this;
		}else
		if(js.isObject(sel)){
			this.elm= sel;
			this.id= js.obj.add(sel.id,sel);
			return this;
		}
		else{
			if(sel && sel.constructor){
				//alert((typeof sel)+' : '+js.isObject(sel));
			}
			return js(document);
		}
	}// init
	
	/* reserved sel:{
		id: function(sel){return document.getElementById(sel)},
		name: function(sel){return document.getElementsByName(sel)},
		tag: function(sel){return document.getElementsByTagName(sel)},
		body: function(){return document.getElementsByTagName("body")[0]},
		html: function(sel){return js.dom.create(sel)}
	}*/

}// js.core

//link from js() to all function in js
js.core.init.prototype = js;

js.ver= '0.11';
js.is= true; // for check, it is "js"-object

})();//# object js 


// Collection of all objects in JS. Jeder Object kennt alle andere im JS und kann die ändern!
// js.collection= [];//[{elm:null,timerId:null}];
// js.obj - alias zum js.collection 
js.collection= 
js.obj= {
	add: function(id,elm){
		var obj= js.obj[id];
		if(obj){
			if(obj.elm){return id}
			obj.elm= elm;
			return id;
		}
		if(!id){
			elm.id= id= 'id_'+js.generateId();
		}
		js.obj[id]= {id:id,elm:elm,timerId:null};
		return id;
	},
	
	remove: function(id){if(js.obj[id]){delete js.obj[id]}},
	
	// swap two object, for event copy use js.event.copy
	swap: function(elm1,elm2){
		var el1= js(elm1).elm;
		var el2= js(elm2).elm;
		js.obj[el1.id].elm= el2;
		js.obj[el2.id].elm= el1;
		var id1= el1.id;
		var id2= el2.id;
		js.obj[id1].elm.id= id1;
		js.obj[id2].elm.id= id2;
	},
	
	getTimer: function(id){return js.obj[id].timerId},
	
	setTimer: function(id,callback,delay){
		var res;
		var obj= js.obj[id];
		obj.stop=0;
		delay= delay || 75;
		
		function _stop(id){
			var obj= this;
			js.obj.clearTimer(id);
			if(typeof obj.final == 'function'){
				try{obj.final.call(obj,obj.final.args);}catch(e){}
			}
		}
		
		function _loop(){
			if(obj.stop){_stop.call(obj,id);return}
			if(obj.pause){return}
			if(callback.call(obj,id) === false){_stop.call(obj,id)}
		}
		_loop();
		obj.timerId= setInterval(_loop,delay);
	},
	
	clearTimer: function(id){
		var obj= js.obj[id];
		clearInterval(obj.timerId);
		clearTimeout(obj.timeoutId);
		obj.timerId= null;
		obj.timeoutId= null;
		obj.stop=0;
		obj.pause=0;
		obj.timeout=0;
	}
}

js.initTimer= function(){
	js.obj[this.id].stop=0;
	js.obj[this.id].timeout=0;
}


/**
 * Set timer for object
 * @param object opt - options:
{
	callback: [function(args){},delay,args],
	timeout: [function(args){},delay,args],
	final: [function(args){},args]
}
*/
js.setTimer= function(opt){
	var id= this.id;
	js.obj.setTimer(id,opt.callback[0],opt.callback[1]);
	
	if(opt.timeout && (typeof opt.timeout[0] == 'function') && opt.timeout[1] > 0){
		js.obj[id].timeoutId= setTimeout(function(){
			js.obj.clearTimer(id);
			try{opt.timeout[0].call(js.obj[id],opt.timeout[3])}catch(e){}
		},opt.timeout[1]);
	}
	
	if(opt.final && (typeof opt.final[0] != 'function')){return this}
	js.obj[id].final= opt.final[0];
	js.obj[id].final.args= opt.final[1];
	return this;
}

js.stopTimer= function(){
	js.obj[this.id].stop=1;
}

js.pauseTimer= function(){
	js.obj[this.id].pause=1;
}

js.continueTimer= function(){
	js.obj[this.id].pause=0;
}

js.clearTimer= function(){
	js.obj.clearTimer(this.id);
}

js.browser= {
	is: function(str){return (navigator.userAgent.indexOf(str) != -1)},
	ua: navigator.userAgent,
	ver: navigator.appVersion,
	
	ie: (navigator.userAgent.indexOf('MSIE') != -1),
	opera: (navigator.userAgent.indexOf('Opera') != -1),
	ff: (navigator.userAgent.indexOf('Firefox') != -1),
	chrome: (navigator.userAgent.indexOf('Chrome') != -1),
	safari: (navigator.userAgent.indexOf('Safari') != -1  && navigator.userAgent.indexOf('Chrome') == -1),
	konqueror: (navigator.userAgent.indexOf('konqueror') != -1),
	
	webkit: (navigator.userAgent.indexOf('WebKit') != -1), // Safari
	khtml: (navigator.userAgent.indexOf('KHTML') != -1),
	mozilla: (navigator.userAgent.indexOf('Mozilla') != -1),
	gecko: (navigator.userAgent.indexOf('Gecko') != -1)
}//
//var tmp= '';for(var i in js.browser){tmp+= i+': '+js.browser[i]+'\n';}alert(tmp);

// http://www.spravkaweb.ru/css/reference/attributes/border_and_layout/boxsizing
js.support= {
	boxModel: null,
	borderBox: function(elm){
		if(js.support.boxModel == null){
			js.support.boxModel= js.getStyle(elm,'-moz-box-sizing') == 'border-box' || js.getStyle(elm,'-webkit-box-sizing') == 'border-box' || js.getStyle(elm,'box-sizing') == 'border-box';
		}
		return js.support.boxModel;
	}	
}

/**
 * usefull ist for: array, object
 * return undefined, array, boolean, string, number, object, function
 */
js.typeOf= function(o){
	if(typeof o == 'object' && o.pop){return 'array'}
	return typeof o;
}

// All is-function work without object quickly as with object
// Note: if(!js.isObject(obj)){} is quickly as if(js.isArray(arr)) in 2 times!
js.isDefined= function(o){return o != undefined}
js.isBool= function(o){return typeof o == 'boolean'}
js.isOBool= function(o){return (o instanceof Boolean)} // o= new Boolean; typeof o == object 
//js.isOBool= function(o){return (o && (o.constructor === Boolean))} // slow // o= new Boolean; typeof o == object 
js.isArray= function(o){return (typeof o == 'object' && o.pop)} // == [] == (new Array)
//js.isArray1= function(o){return o instanceof Array} // == [] == (new Array)

js.isObject= function(o){return (typeof o == 'object' && !o.pop)}   // quickly // == {} == (new Object) == (new function(){}) == (new Date) == (new String) == (new XLMHtpReques).. != [] != 1 .. 
js.isOObject= function(o){return (o && (o.constructor === Object))} // slow    // == {} == (new Object) != (new function(){}) != (new Date) != (new String) != (new XLMHtpReques).. != [] != 1 ..

// Native typeof
js.isString= function(o){return typeof o == 'string'}
js.isNumber= function(o){return typeof o == 'number'}
js.isFunction= function(o){return typeof o == 'function'}

js.formatOf= function(){
	var val= arguments.length ? arguments[0] : this;
	val=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/);
	if(!val[3]){val[3]='px'}
	return val;
}

js.count= function(obj,fn){
	var isFn= js.isFunction(fn);
	var count= 0;
	var prop;
	for(prop in obj){
		if(isFn){
			if(fn.call(obj[prop])===false){continue}
		}
		count++
	}
	return count;
}

js.toInt= function(){
	var val= arguments.length ? arguments[0] : this;
	return parseInt(val,10) || 0;
}

js.toFloat= function(){
	var val= arguments.length ? arguments[0] : this;
	return parseFloat(val) || 0;
}

//reserv
js.toHex= function(){
	var val= arguments.length ? arguments[0] : this;
	return val
},

// reserv
js.toDec= function(){
	var val= arguments.length ? arguments[0] : this;
	return val
}

//Get element & value from functions arguments. Used by function with GET || SET methode
var getArgs= function(arg){
	var elm=val=undefined;
	for(var i=0;i<arg.length&&i<2;i++){
		if(typeof arg[i] == 'object'){elm= arg[i];}else
		if(typeof arg[i] == 'string' || typeof arg[i] == 'number'){val= arg[i];}
	}
	return {'elm':elm,'val':val}
}

/* @param:
 * function,
 * state (only for Elements and not for document!): 
 * 		onLoad 	 	- HTML is only loaded and not rendered
 * 		onRender	- HTML is loaded and rendered (width || height > 0), wait 10 sec. (Default)
 * 		onDisplay 	- HTML is rendered and visible, wait to visible, same as onRender but w/o timeout
 */
js.onReady= function(){
	var self= this;
	var fn= null;
	var state= 'onrender'; // default
	for(var i=0; i<arguments.length&&i<2;i++){
		if(typeof arguments[i] == 'function'){fn= arguments[i];}
		else{state= arguments[i];}
		if(state.length){state= state.toLowerCase();}
	}
	if(!fn){return false;}
		
	var timeout= 10; // sec.
	var delay= 5; // delay in ms
	var count= timeout * (Math.floor(1000/delay) || 1);// count of steps
	var tReady= 0;		
	
	var isRendered= false;
	if(state == 'onload'){isRendered= false;}
	else if(state == 'onrender'){isRendered= true;}
	else if(state == 'ondisplay'){timeout= 0;isRendered= true;}
	
	// for document
	// IE6/7, FF3.5, Opera 9.2, Chrome 3, Safari 3, SeaMonkay 1.1
	// wait on load all DOM Elements, but not on full load of Images! it is ready!
	var body= null;
	var nodesLen= 0;
	var isDocumentReady= function(){
		var curNodesLen= body.childNodes.length;
		if(curNodesLen > nodesLen){
			nodesLen= curNodesLen;
			return false;
		}
		return true;		
	}
	// for DOM Elements
	var isElementReady= function(){
		self.elm= document.getElementById(self.id);
		return ( (isRendered && self.elm && self.elm.offsetHeight) || (!isRendered && self.elm) );
	}
	var isReady;
	
	if(self.elm && self.elm.id == 'document'){//
		body= document.getElementsByTagName("body")[0];
		isReady= isDocumentReady;
	}else{isReady= isElementReady}
	
	function _loop(){
		if(isReady()){
			clearInterval(tReady);tReady= 0;
			fn.call(self,self.elm);
			return;
		}else if(timeout){
			if(count < 1){
				clearInterval(tReady);
				alert('SYSERROR: Timeout > '+timeout+' sec.\nElement "#'+self.id+'" not found!');
				return;
			}
			count--;	
		}
		if(!tReady){tReady= setInterval(function(){_loop()},delay);}
	}// wait
	_loop();
}// onReady

// js('inp_btn','name').each(function(params){alert(params)},[params]);
/*
js.each= function(){
	var self= this;
	var elms;
	var iFn;
	if(!arguments.length){
		return;
	}else
	if(arguments.length > 1){
		elms= arguments[0];
		iFn= 1;
	}else{
		elms= this;
		iFn= 0;
	}
	
	var elm_type= js.typeOf(elms);
	if(elm_type == 'array'){
		for(var i=0;i<elms.length;i++){
			arguments[iFn].call(elms[i],arguments[2]);
		}
	}else
	if(elm_type = 'object'){;
		if(elms.elm){
			elms= elms.elm;
		}
		for(var elm in elms){alert(elm)
			arguments[iFn].call(elm,arguments[2]);
		}
	}else{
		arguments[iFn].call(elms,arguments[2]);
	}
	
}*/

//js.each({key:'val'},function(key,val){})
js.each= function(){
	var elms, iFn;
	if(!arguments.length){return}
	
	if(arguments.length > 1){// hier kann nur 1 elm oder object oder array sein
		elms= arguments[0];
		iFn= 1;
	}else{// hier kann nur 1 elm oder array sein
		elms= this;
		iFn= 0;
	}

	if(js.isObject(elms)){;
		if(elms.elm){
			elms= elms.elm;
		}
		for(var key in elms){
			var val= elms[key];
			arguments[iFn].call(this,key,val);
		}
	}
}
	
//Quirks or Standards mode
//js.body= (document.compatMode == 'CSS1Compat' && /*!js.browser.opera*/ !document.body) ? document.documentElement : document.body;

/*
js.body= function(){
	if(document.compatMode == 'CSS1Compat' && !js.browser.opera && !js.browser.chrome){
		return document.documentElement;
	}else{
		return document.body;
	}
}
*/

js._elm= document.createElement('div'); // test element for compability

js.isBody= function(elm){
	var elm= elm.tagName.toLowerCase();
	return (elm == 'body' || elm == 'html');
}

js.getWindowWidth= function(){
	//return js.body.clientWidth;
}

js.getWindowHeight= function(){
	//return js.body.clientHeight;
}

js.getDocumentWidth= function(){
	//return js.body.clientWidtht + js.body.o;
}

js.getDocumentHeight= function(){
	//return js.body.clientHeight + js.body.o;
}

/*js.getDocumentSize= function(){
	return {w:js.getDocumentWidth(),h:js.getDocumentHeight()}
}*/

// http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html
// on site reload in IE scroll ist immer 0!
js.getScroll= function(elm){
	var x,y= 0;
	if(!elm || js.isBody(elm)){
		if(!document.body){return{x:0, y:0}}
		x= Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
		y= Math.max(document.documentElement.scrollTop, document.body.scrollTop);
	}else{
		x= elm.scrollLeft;
		y= elm.scrollTop;
	}
	return{x:x, y:y}
}

js.height= function(){// #
	var args= getArgs(arguments);
	return js.element.size((args.elm || this.elm),'height','',args.val);
}
js.innerHeight= function(){
	var args= getArgs(arguments);
	return js.element.size((args.elm || this.elm),'height','inner',args.val);
}
js.outerHeight= function(){
	var args= getArgs(arguments);
	return js.element.size((args.elm || this.elm),'height','outer',args.val);
}
js.width= function(){// #
	var args= getArgs(arguments);
	return js.element.size((args.elm || this.elm),'width','',args.val);
}
js.innerWidth= function(){
	var args= getArgs(arguments);
	return js.element.size((args.elm || this.elm),'width','inner',args.val);
}
js.outerWidth= function(){
	var args= getArgs(arguments);
	return js.element.size((args.elm || this.elm),'width','outer',args.val);
}

// http://paularmstrongdesigns.com/projects/basejs/docs/
js.element= {
	
	/**
	* js.element.create('div',{id:'d1',style:{width:'200px',opacity:50,color:'#FF0000'}},'<span>content</span>')
	* js.element.create('div',{id:'iframe1',name:'iframe1',src:'javascript:false;',style:{width:'10px',height:'10px',position:'absolute',top:0,left:0;}},'')
	*/
	create: function(tag,attrs,content){ 
		var elm;
		if(tag == 'iframe'){elm= js.dom.create('<iframe></iframe>')}
		else{elm= document.createElement(tag)}
		var attr;
		for(attr in attrs){
			if(attr == 'style'){
				js.elm= elm; // anonyme for JS
				js.css(attrs[attr]);
				continue;
			}
			//elm.setAttribute(attrs[attr]);
			elm[attr]= attrs[attr];
		}
		if(content){try{elm.innerHTML= content}catch(e){}}
		return elm;
	},
	
	/**
	* parce style string to css object
	* opacity:20; width:30px => {opacity:20,width:30px}
	*/
	/*parseStyle: function(style){
		style= style.replace(';',',');
		var css;
		eval('css=({'+style+'})');
		return css;
	},
	parseStyle1: function(style){
		style= style.split(';');
		var len= style.length;
		var css;
		var s;
		for(var i=0;i>len;i++){
			s= style[i].split(':');
			css[s[0]]=s[1];
		}
		return css;
	},*/
	
	position: function(elm){
		var rect= elm.getBoundingClientRect();
		var body = document.body; 
		var docElm = document.documentElement;
		var scroll= {x:0,y:0};
		if(js.getStyle(elm,'position') != 'fixed' /*&& js.support.borderBox(elm)*/){
			scroll= js.getScroll();
		}
		 
		var clientX = docElm.clientLeft || body.clientLeft || 0;
		var clientY = docElm.clientTop || body.clientTop || 0;
		
		var x= rect.left + scroll.x - clientX;
		var y= rect.top  + scroll.y - clientY;
		return {x: x,y: y}
	},
	
	// GET - if val is undefined
	// SET - if is val
	// elm - object of element
	// param - width | height
	// opt - outer | inner
	// val - for SET, value in unit (px,em,..)
	size: function(elm,param,opt,val){
		var o,v;
		if(elm == document){elm= document.getElementsByTagName("body")[0];}
		if(param == 'width'){
			o= ['left','right'];
			//if(elm == document){elm= js.body}
			v= elm.offsetWidth;
		}else
		if(param == 'height'){
			o= ['top','bottom'];
			v= elm.offsetHeight;
		}else{return false;}
		// GET
		if(val == undefined){
			v= parseFloat(v);
			if(opt == 'outer'){
				v+= js.toInt(js.getStyle(elm,'margin-'+o[0])) + js.toInt(js.getStyle(elm,'margin-'+o[1]));
			}else
			if(opt == 'inner'){
				v-= js.toInt(js.getStyle(elm,'padding-'+o[0])) + js.toInt(js.getStyle(elm,'padding-'+o[1])) + js.toInt(js.getStyle(elm,'border-'+o[0]+'-width')) + js.toInt(js.getStyle(elm,'border-'+o[1]+'-width'));
			}
			return v;
		}
		// SET
		var unit= js.formatOf(val);
		if(opt == 'outer'){
			if(unit[3] == 'px'){
				val= (unit[2] - js.toInt(js.getStyle(elm,'padding-'+o[0])) - js.toInt(js.getStyle(elm,'padding-'+o[1])) - js.toInt(js.getStyle(elm,'border-'+o[0]+'-width')) - js.toInt(js.getStyle(elm,'border-'+o[1]+'-width')) - js.toInt(js.getStyle(elm,'margin-'+o[0])) - js.toInt(js.getStyle(elm,'margin-'+o[1])) ) + 'px';
			}
		}else
		if(opt == 'inner'){
			val= unit[2]+unit[3]; // h + unit (px,..) 
		}else{
			if(unit[3] == 'px'){
				val= (unit[2] - js.toInt(js.getStyle(elm,'padding-'+o[0])) - js.toInt(js.getStyle(elm,'padding-'+o[1])) - js.toInt(js.getStyle(elm,'border-'+o[0]+'-width')) - js.toInt(js.getStyle(elm,'border-'+o[1]+'-width')) ) + 'px';
			}
		}
		return elm.style[param]= val;
	}

}// layout

// return {x,y}
js.position= function(){
	return js.element.position(this.elm);
}

//CSS Access
// http://xpoint.ru/know-how/JavaScript/TablitsyiStiley?2
js.getComputedStyle= document.defaultView ? 
function(elm){return document.defaultView.getComputedStyle(elm,null)}:
function(elm){return elm.currentStyle || elm.style;}


js.getStyle= js.getComputedStyle(js._elm).getPropertyValue ?
function(elm,prop){ // FF, Opera7+, Safari 1.3+
	var computedStyle= js.getComputedStyle(elm);
	if(prop.match(/[A-Z]/)){
		prop= prop.replace(/([A-Z])/g, '-$1').toLowerCase();
	}
	return computedStyle.getPropertyValue(prop);
}:
function(elm,prop){ // IE, Opera9
	var computedStyle= js.getComputedStyle(elm);
	var i;
	while((i=prop.indexOf('-'))!=-1){
		prop= prop.substr(0,i) + prop.substr(i+1,1).toUpperCase() + prop.substr(i+2); // z-index => zIndex 
	}
	return computedStyle[prop];
}

// http://www.w3.org/TR/2008/REC-CSS2-20080411/syndata.html
// Relative units:
//* em: the 'font-size' of the relevant font, 1em equal to 12pt
//* ex: the 'x-height' of the relevant font
//* px: pixels, relative to the viewing device 
// Absolute units:
//* in: inches -- 1 inch is equal to 2.54 centimeters.
//* cm: centimeters
//* mm: millimeters
//* pt: points -- the points used by CSS2 are equal to 1/72th of an inch.
//* pc: picas -- 1 pica is equal to 12 points. 
// Percentages:
//* [+||-]<number>%

//* color: rgb(255,0,0)        /* integer range 0 - 255 */
//* color: rgb(300,0,0)        /* clipped to rgb(255,0,0) */
//* color: rgb(255,-10,0)      /* clipped to rgb(255,0,0) */
//* color: rgb(110%, 0%, 0%)   /* clipped to rgb(100%,0%,0%) */

js.color= {
	name:{
		transparent: [255,255,255]
	},
		
	// Color Conversion functions from highlightFade
	// By Blair Mitchelmore
	// http://jquery.offput.ca/highlightFade/

	// Parse strings looking for color tuples [255,255,255]
	getRGB: function(color) {
		var result;
		// Check if we're already dealing with an array of colors
		if ( js.isArray(color) )
				return color;
		// Look for rgb(num,num,num)
		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
		// Look for rgb(num%,num%,num%)
		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
		// Look for #a0b1c2
		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];

		// Look for #fff
		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];

		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
				return js.color.name['transparent'];
				
		if(!color){return js.color.name['transparent'];}
				
		// Otherwise, we're most likely dealing with a named color
		result= js.color.name[color.toLowerCase()];
		return result ? result : [0,0,0];
	}
}// color

/**
 * Get oder Set CSS property
 * usage to get:
 js(elm).css('opacity')
 
 * usage to set:
 js(elm).css({opacity:0,position:'absolute',zIndex:1}); // shot 
 js(elm).css('opacity',0).css('position','absolute').css('zIndex','1'); // quicly
 
 */
js.css= function(){
	var prop, value;
	if(arguments.length == 2){
		prop= arguments[0];
		value= arguments[1];
	}else
	if(js.isObject(arguments[0])){;
		for(var prop in arguments[0]){js.css.call(this,prop,arguments[0][prop])}
		return this;
	}else
	if(typeof arguments[0] == 'string'){
		prop= arguments[0];
	}else{alert('ERROR: not defined usage of js.css!'); return this;}
	
	// GET/SET Property
	if(prop == 'width' || prop == 'height'){
		if(value == undefined){return js.element.size(this.elm,prop)}
		else{js.element.size(this.elm,prop,'',value);return this;}
	}
	
	if(prop.toLowerCase().indexOf('color') >= 0){
		if(value == undefined){return js.color.getRGB(js.getStyle(this.elm,prop));}
		else{this.elm.style[prop]= (value == 'none') ? '' : 'rgb('+js.color.getRGB(value).toString()+')';return this;}
	}
	
	// GET Property
	if(value == undefined){
		if(js.css.property[prop] && js.css.property[prop].get){
			return js.css.property[prop].get(this.elm);
		}
		return js.getStyle(this.elm,prop);
	}
	
	// SET Property
	if(prop.indexOf('background-position') >= 0){
		var s= js.getStyle(this.elm,'background-position');
		if(s != undefined){
			var pos= js.getStyle(this.elm,'background-position').split(' ');   
			if(prop.indexOf('x') > 0){value= value+' '+pos[1];}else
			if(prop.indexOf('y') > 0){value= pos[0]+' '+value;}
			prop= 'backgroundPosition';
		}else{
			prop= 'backgroundPosition';
			if(prop.indexOf('x') > 0){prop+= 'X';}else
			if(prop.indexOf('y') > 0){prop+= 'Y';}				
		}
	}else
	if(js.css.property[prop]){
		if(js.css.property[prop].set){
			js.css.property[prop].set(this.elm,value);
			return this;
		}
		prop= js.css.property[prop];
	}
	this.elm.style[prop]= value;
	return this;
}// css

js.css.elm= document.createElement('div');
js.css.property= {}

js.css.property.float= (js.css.elm.style.cssFloat != undefined) ? 'cssFloat' : 'styleFloat';
/*
 * TODO: all color propertys - background-color; font-color, etc.
js.css.property.color=
	{
		get: function(elm){return js.color.getRGB(js.getStyle(elm,'color'))},
		set: function(elm,val){elm.style.color= 'rgb('+js.color.getRGB(val).toString()+')';}
	}
*/
js.css.property.opacity= 
	(js.css.elm.style.opacity != undefined) ?
	{
		get: function(elm){return js.getStyle(elm,'opacity')*100 || 100},
		set: function(elm,val){elm.style.opacity= val/100}
	} : 
	(js.css.elm.style.MozOpacity != undefined) ?
	{
		get: function(elm){return js.getStyle(elm,'MozOpacity')*100 || 100},
		set: function(elm,val){elm.style.MozOpacity= val/100}
	} :
	(js.css.elm.style.KhtmlOpacity != undefined) ?
	{
		get: function(elm){return js.getStyle(elm,'KhtmlOpacity')*100 || 100},
		set: function(elm,val){elm.style.KhtmlOpacity= val/100}
	} :	
	(js.css.elm.style.filter != undefined) ?
	{
		get: function(elm){
			var filter= js.getStyle(elm,'filter');
			var opacity= filter.match(/\(opacity=(.+)\)/i);
			return (opacity == null) ? 100 : opacity[1];
		},
		set: function(elm,val){elm.style.filter= 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + val + ')'}
		//set: function(elm,val){elm.style.filter= 'alpha(opacity=' + val + ')'}
	} : null;
	
// Check exist class name
js.hasClass= function(className){
	var patt= new RegExp('(^| )'+className+'( |$)');
	if(this.elm.className.search(patt) < 0){return false}
	return true;
}

js.setClass= function(className){
	this.elm.className= className;
	return this;
}

js.addClass= function(className){
	if(this.hasClass(className)){return this} // if the className exist, than not insert this
	if(this.elm.className.length){this.elm.className+= ' ';}
	this.elm.className+= className;
	return this;
}

// remove className1 and add className2
js.removeClass= function(className1, className2){
	var patt= new RegExp('(?:^| )'+className1+'(?: |$)');
	this.elm.className= this.elm.className.replace(patt,' ').ftrim(); // class != (class)111
	if(className2){
		return this.addClass(className2);
	}
	return this;
}

// if className1 not exist, than className2 not insert
js.replaceClass= function(className1, className2){
	this.elm.className= this.elm.className.replace(className1,className2);
	return this;
}

// if className not exist than insert it, otherwise remove it
// TODO: testen 
js.toggleClass= function(className){
	if(this.hasClass(className)){
		return this.removeClass(className);
	}
	return this.addClass(className);
}

//
js.show= function(fn){
	if(!this.elm){return false;}
	this.elm.style.display= 'block';
	this.elm.style.visibility= 'visible';
}
js.hide= function(fn){
	if(!this.elm){return false;}
	this.elm.style.display= 'none';
}


// DOM
js.dom= {}

/**
 * Creates and returns element from html string
 * Uses innerHTML to create an element
 */
js.dom.create= function(html){
	var elm= document.createElement('div'); 
	elm.innerHTML= html;
	return elm.firstChild;
}

// add the elm as first into js(sel)
js.addFirst= function(elm){this.elm= js.dom.addFirst(elm,this.elm);return this;}
// add js(sel) into elm as first
js.addFirstTo= function(elm){this.elm= js.dom.addFirst(this.elm,elm);return this;}
// add the elm as last into js(sel)
js.addLast= function(elm){this.elm= js.dom.addLast(elm,this.elm);return this;}
// add js(sel) into elm as last
js.addLastTo= function(elm){this.elm= js.dom.addLast(this.elm,elm);return this;}
// add the elm befor js(sel)
js.addBefor= function(elm){this.elm= js.dom.addBefor(elm,this.elm);return this;}
// add js(sel) befor elm
js.addBeforBy= function(elm){this.elm= js.dom.addBefor(this.elm,elm);return this;}
// add the elm after js(sel)
js.addAfter= function(elm){this.elm= js.dom.addAfter(elm,this.elm);return this;}
//add js(sel) after elm
js.addAfterBy= function(elm){this.elm= js.dom.addAfter(this.elm,elm);return this;}

js.next= js.nextElement= function(){this.elm= js.dom.next(this.elm);return this;}
js.prev= js.prevElement= function(){this.elm= js.dom.prev(this.elm);return this;}
js.remove= js.removeElement= function(){
	js.dom.walk(this.elm, function(){
		js.obj.remove(this.id); // remove all sub-elements from collection 
		return false;
	})
	this.elm= js.dom.remove(this.elm); // remove element from dom
	return this;
}
js.replace= js.replaceElement= function(elm){return js.dom.replace(elm,this.elm);}

/**
 * add newElm als first chils to elm1
 * js.dom.addFirst(newElm) - add newElm as first child to BODY
 * js.dom.addFirst(newElm,toElm) - add newElm as first child to toElm
 */
js.dom.addFirst= function(newElm,toElm){
	if(typeof newElm == 'string'){newElm= js.dom.create(newElm)}
	if(!toElm){
		toElm= js('body').elm;
	}
	return toElm.firstChild ?
		toElm.insertBefore(newElm,toElm.firstChild) :
		toElm.appendChild(newElm);
}

/**
 * add newElm als last child to toElm
 * js.dom.addLast(newElm) - add newElm as last child to BODY
 * js.dom.addLast(newElm,toElm) - add newElm as last child to toElm
 */
js.dom.addLast= function(newElm,toElm){
	if(typeof newElm == 'string'){newElm= js.dom.create(newElm)}
	if(toElm){
		return toElm.appendChild(newElm)
	}
	return js('body').elm.appendChild(newElm);
}

js.dom.addBefor= function(newElm,beforElm){
	if(typeof newElm == 'string'){newElm= js.dom.create(newElm)}
	return beforElm.parentNode.insertBefore(newElm,beforElm);
}

js.dom.addAfter= function(newElm,afterElm){
	if(typeof newElm == 'string'){newElm= js.dom.create(newElm)}
	var nextElm= js.dom.next(afterElm);
	if(nextElm){
		return js.dom.addBefor(newElm,nextElm);
	}
	return afterElm.parentNode.appendChild(newElm);
}

js.dom.remove= function(eml){
	return eml.parentNode.removeChild(eml);
}

js.dom.replace= function(newElm,oldElm){
	if(typeof newElm == 'string'){newElm= js.dom.create(newElm)}
	return oldElm.parentNode.replaceChild(newElm,oldElm);
}

/**
 * IE fix - check if the next sibling node is an element node
 */
js.dom.next= function(elm){
	do{elm= elm.nextSibling;}while(elm && elm.nodeType != 1);
	return elm;
}//

/**
 * IE fix - check if the previous  sibling node is an element node
 */
js.dom.prev= function(elm){
	do{elm= elm.previousSibling;}while(elm && elm.nodeType != 1);
	return elm;
}//

js.dom.getParentByTagName= function(node,tagName){
	for(;node && node.nodeName.toLowerCase() != tagName; node=node.parentNode);
	return node ? node : null;
}

js.dom.walk= function(node,fn){
	var response;
	try{
		if(response=fn.call(node)){return response;}
	}catch(e){}
	node= node.firstChild;
	while(node){
		if(response=js.dom.walk(node,fn)){return response;}
		node= js.dom.next(node);
	}
}//

js.findChildByParentId= function(parent_id,find_id){
	var elm= document.getElementById(parent_id);
	if(!elm){return null}
	
	var compare= function(){
		if(this.id && this.id == find_id){return this;}
		return false;
	}
	
	return js.dom.walk(elm,compare);
}


//::: MISC :::

js.redirect= function(url){
	window.location.replace(url+'?&'+js.tstamp());
}//

//Timestamp
js.msec= function(){
	var time= new Date();
	return time.getTime();
}

js.tstamp= function(){
	return parseInt(js.msec()/1000,10);
}

/**
 * generate ID
 * return string length(8)
 */
js.generateId= function(){
	//return js.msec().toString().substr(5);// length(8), repeat 1x pro 27 hour
	return parseInt(Math.random().toString().substr(2),10).toString().substr(0,8); // w/o begin nulls
}

js.rnd= function(){
	return parseInt(Math.random().toString().substr(2),10);
}

// TODO:

function getDocumentSize(){
	var w1= 0;
	var h1= 0;
	if(window.innerHeight){
		w1= js.toInt(window.innerWidth);
		h1= js.toInt(window.innerHeight);
	}

	var w2= 0;
	var h2= 0;
	if(document.body){
		w2= js.toInt(document.body.clientWidth);
		h2= js.toInt(document.body.clientHeight);
	}

	var w3= 0;
	var h3= 0; 
	if(document.documentElement){
		w3= js.toInt(document.documentElement.clientWidth);
		h3= js.toInt(document.documentElement.clientHeight);
	}
	
	return{
		w: Math.max(Math.max(w1,w2),w3),
		h: Math.max(Math.max(h1,h2),h3)
	}
}//

function getBrowserWidth(){
	var clientWidth;
	if (window.innerWidth){
		clientWidth = (window.__safari ? window.innerWidth : Math.min(window.innerWidth, document.documentElement.clientWidth));
	}else if (document.documentElement && document.documentElement.clientWidth){
		clientWidth = document.documentElement.clientWidth;
	}else if (document.body){
		clientWidth = document.body.clientWidth;
	}else {
		clientWidth = document.documentElement.clientWidth;
	}
	return parseInt(clientWidth,10);
}//#

function getBrowserHeight(){
	var clientHeight;
	if (window.innerHeight) {
		clientHeight = (window.__safari ? window.innerHeight : Math.min(window.innerHeight, document.documentElement.clientHeight));
	}else if (document.documentElement && document.documentElement.clientHeight){
		clientHeight = document.documentElement.clientHeight;
	}else if (document.body){
		clientHeight = document.body.clientHeight;
	}else {
		clientHeight = document.documentElement.clientHeight;
	}
	return parseInt(clientHeight,10);
}//#


// JS Extensions

// ### Function ###

// js.event.add(elm, type, function(){alert(this.href)}.bind(elm));
if(!Function.prototype.bind){
	Function.prototype.bind= function(obj){
		var method = this;
		return function(){return method.apply(obj, arguments)}
	}
}

// ### String ###

// trim
if (typeof String.prototype.trim == 'undefined') {
	String.prototype.trim= function(){return this.replace(/^\s+/, '').replace(/\s+$/, '')}
}

//ftrim - fullTrim: left + inner + right
if (typeof String.prototype.ftrim == 'undefined') {
	String.prototype.ftrim= function(){return this.replace(/^\s+/, '').replace(/\s{2,}/, ' ').replace(/\s+$/, '')}
}

//itrim - innerTrim, " ABC  QWE ERT  " =>  " ABC QWE ERT "
if (typeof String.prototype.itrim == 'undefined') {
	String.prototype.itrim= function(){return this.replace(/\s{2,}/, ' ')}
}

// ltrim
if (typeof String.prototype.ltrim == 'undefined') {
	String.prototype.ltrim= function(){return this.replace(/^\s+/, '')}
}

// rtrim
if (typeof String.prototype.rtrim == 'undefined') {
	String.prototype.rtrim= function(){return this.replace(/\s+$/, '')}
}

// ### Array ###

// indexOf - find index of value in array 
if(!Array.prototype.indexOf){
	Array.prototype.indexOf= function(value, offset){
		for(var i= offset||0, length= this.length; i<length; i++){
			if(this[i] === value) return i;
		}
		return -1
	};
}

