/*
 * JavaScript css framework: js
 * Version 0.2.0a
 * Dmitrij Sosnovsenko
 * biodiscus@gmail.com
 *
 * last update: 2011-12-13
 */

/**
 * Methods for CSS
 *
 * required: js_core.js
 * required: js_dom.js
 */


/**
 * 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{
			//alert(value + ' ; '+js.color.getRGB(value));
			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){
			var opacity = js.getStyle(elm,'opacity');
			return opacity == '' ? 100 : opacity*100;
		},
		set: function(elm,val){elm.style.opacity= val/100}
	} :
	(js.css.elm.style.MozOpacity != undefined) ?
	{
		get: function(elm){
			var opacity = js.getStyle(elm,'MozOpacity');
			return opacity == '' ? 100 : opacity*100;
		},
		set: function(elm,val){elm.style.MozOpacity= val/100}
	} :
	(js.css.elm.style.KhtmlOpacity != undefined) ?
	{
		get: function(elm){
			var opacity = js.getStyle(elm,'KhtmlOpacity');
			return opacity == '' ? 100 : opacity*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;

// return all styles (not css from class) from element as object
js.getStyles= function(){
	return js.css.getStyles(this.elm);
}
js.css.getStyles= function(elm){
	var elmStyles= elm.style;
	var key,style;
	var oStyles= {};
	for(key in elmStyles){
		style= elmStyles[key];
		if(typeof key != 'string' || key.length < 3){continue}
		if(typeof style != 'string' || style.length < 1){continue;}
		oStyles[key]= style;
	}
	return oStyles;
}


//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

// *** 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.css.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.spravkaweb.ru/css/reference/attributes/border_and_layout/boxsizing
js.support= {
	boxModel: '',
	contentBox: 0,
	paddingBox: 0,
	borderBox: 0,
	getBoxModel: function(elm){
		js.support.contentBox= js.support.paddingBox= js.support.borderBox= 0;
		//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';
		js.support.boxModel= js.getStyle(elm,'-moz-box-sizing') || js.getStyle(elm,'-webkit-box-sizing') || js.getStyle(elm,'box-sizing');

		if(js.support.boxModel == 'content-box'){js.support.contentBox= 1}else
		if(js.support.boxModel == 'padding-box'){js.support.paddingBox= 1}else
		if(js.support.boxModel == 'border-box'){js.support.boxModel= 1}

		return js.support.boxModel;
	}
}

// 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);
}


if(js.browser.ie){
	// Stop IE6 re-loading background images continuously
	try {
	  document.execCommand("BackgroundImageCache", false, true);
	} catch(err) {}
}
