/*
 * pettanR libs.js
 *   version 0.5.47
 * 
 * 
 * Type
 * 
 * UA
 * 
 * Util
 * 
 * CSS
 * 
 */

if( !( 'console' in window ) ){
	window[ 'console' ] = { log : function(){} };
}

var getFunctionName = function( f ){
    return 'name' in f
        ? f.name
        : (''+f).replace(/^\s*function\s*([^\(]*)[\S\s]+$/im, '$1');
};

/*
 * http://d.hatena.ne.jp/hir90/20080620/1213987444
 */
	String.prototype.repeat = function( num){
		var str = "" + this;
		var ans = '';
		if( num < 0) return 'error';
		while( num){
			if( num&1) ans += str;
			num = num>>1;
			str += str;
		}
		return ans;
	}

/*
 * http://pettanr.sourceforge.jp/test/type.html
 */
	var Type = {
		isObject : function(v) {
			return v !== null && typeof v === 'object';
		},
		isFunction : function(v) {
			return typeof v === 'function';
		},
		isArray : function(v) {
			return Object.prototype.toString.call(v) === '[object Array]';
		},
		isBoolean : function(v) {
			return typeof v === 'boolean';
		},
		isString : function(v) {
			return typeof v === 'string';
		},
		isNumber : function(v) {
			return typeof v === 'number';
		},
		isFinite : function(v){
			return Type.isNumber(v) === true && isFinite(v);
		},
		isHTMLElement : function(v){
			if( 'HTMLElement' in window ){
				Type.isHTMLElement = function(v){
					return v instanceof HTMLElement;
				};
			} else {
				Type.isHTMLElement = function(v) {
					if( Type.isObject(v) === false ){
						return false;
					};
					var r;
					if(v && v.nodeType === 1 ){
						try {
							r = v.cloneNode(false);
						} catch(n){
							return false;
						};
						if(r === v) return false;
						try{
							r.nodeType = 9;
							return r.nodeType === 1;
						} catch(n){};
						return true;
					};
					return false;
				};
			};
			return Type.isHTMLElement(v);
		},
		/*
		isElementCollection : function(v) {
			return (Object.prototype.toString.call(v) === "[object HTMLCollection]");
		},
		*/
		isNull : function(v) {
			return v === null;
		},
		isUndefined : function(v) {
			return typeof v === 'undefined';
		}
	};

/*
 * UA
 * 
 *   detect userAgent
 *   detect plug in
 */
	var UA = ( function(){
		var ua = (function(){
				var acme = {};
				
				var n    = navigator;
				var dua  = n.userAgent;
				var dav  = n.appVersion;
				var tv   = parseFloat(dav);
				acme.isOpera  = (dua.indexOf("Opera") >= 0) ? tv: undefined;
				acme.isKhtml  = (dav.indexOf("Konqueror") >= 0) ? tv : undefined;
				acme.isWebKit = parseFloat(dua.split("WebKit\/")[1]) || undefined;
				acme.isChrome = parseFloat(dua.split("Chrome\/")[1]) || undefined;
				acme.isGecko  = (dua.indexOf("Gecko\/") >= 0) ? parseFloat(dua.split("rv:")[1].replace( /^(\d*\.\d*)\.(\d*)/, '$1$2' )) : undefined;
				var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);
				if(index && !acme.isChrome){
					acme.isSafari = parseFloat(dav.split("Version/")[1]);
					if(!acme.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){
						acme.isSafari = 2;
					};
				};
				if(document.all && !acme.isOpera){
					acme.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined;
				};
				
				return acme;
			})(),
			isIE = navigator.userAgent.toLowerCase().indexOf( 'msie') !== -1,
			ieVersion = isIE === true ? parseInt( navigator.appVersion.toLowerCase().replace( /.*msie[ ]/, '').match( /^[0-9]+/)) : 0,
			ieRenderingVersion = ieVersion === 8 ? document.documentMode : ieVersion,
			isStanderdMode = document.compatMode === 'CSS1Compat',
			ActiveX = ( function(){
				if( isIE === false || ieVersion > 8 ) return false;
				var	b = document.body,
					c = b.className || '',
					x,
					ret = undefined, //pettanr.URL_PARAMS.ActiveX,
					ns = 'pettanr-ActiveX-',
					enabled = 'enabled',
					disabled = 'disabled';
				if( ret !== true && ret !== false){
					if( b.className.indexOf( ns + enabled ) !== -1 )  return true;
					if( b.className.indexOf( ns + disabled ) !== -1 ) return false;
					x = document.createElement( 'div' );
					b.appendChild(x);
					x.style.cssText = 'width:1px;height:1px;line-height:1px;filter:progid:DXImageTransform.Microsoft.Shadow()';
					ret = x.offsetHeight > 1;
					b.removeChild(x);
				};
				b.className += [ c !== '' ? ' ' : c, ns, ret === true ? enabled : disabled ].join( '');
				return ret;
			})(),
			VML = ( function(){
				if( ActiveX === false || isIE === false || ieVersion > 8) return false;
				var globalObjectName = 'detect_activex',//Util.createGlobalUniqueName(),
					script,
					id = 'detectVML';
				document.write( [ '<!--[if gte vml 1]><script id="', id, '">window', '.', globalObjectName, '=1;<\/script><![endif]-->'].join( ''));
				if( window[ globalObjectName ] === 1 ){
					script = document.getElementById( id );
					script.parentNode.removeChild( script );
					window[ globalObjectName ] = null;
					return true;
				};
				return false;
			})(),
			isStandAloneMode = ( function(){
				if( isIE === false) return false;
				if( VML === true) return false;
				var globalObjectName = 'detect_standalone', //Util.createGlobalUniqueName(),
					script,
					id = 'detectStandAlone';
				document.write( [ '<!--[if IE ', Math.floor( ieVersion ), ']><script id="', id, '">window', '.', globalObjectName, '=1;<\/script><![endif]-->'].join( '' ));
				if( window[globalObjectName] === 1 ){
					script = document.getElementById( id);
					script.parentNode.removeChild( script);
					window[globalObjectName] = null;
					return false;
				};
				return true;
			})();
		return {
			IE:					ua.isIE,
			GECKO:				ua.isGecko,
			OPERA:				ua.isOpera,
			KHTML:				ua.isKhtml,
			WEBKIT:				ua.isWebKit,
			CHROME:				ua.isChrome,
			isIE:				isIE,
			ieVersion:			ieVersion,
			ieRenderingVersion:	ieRenderingVersion,
			isStanderdMode:		isStanderdMode,
			ACTIVEX:            ActiveX,
			VML:                VML,
			STANDALONE:         isStandAloneMode,
			VENDER_PREFIX: ( function() {
				var ua = navigator.userAgent.toLowerCase();
				if ( ua.indexOf('opera') !== -1 ){
					return 'O';
				} else if ( ua.indexOf('msie') !== -1 ){
					return 'ms';
				} else if ( ua.indexOf('webkit') !== -1 ){
					return 'webkit';
				} else if ( navigator.product === 'Gecko' ){
					return 'Moz';
				}
				return '';
			})(),
			startVML: function(){
				delete UA.startVML;
				if( UA.VML !== true) return false;
				if (!document.namespaces["v"]) {
			        document.namespaces.add("v", "urn:schemas-microsoft-com:vml", "#default#VML");
				};
			    document.createStyleSheet().cssText = "v\:shape,v\:image{behavior:url(#default#VML);display:block;};";
			}
		};
	})();


/* ----------------------------------------------------
 * Util
 * 
 *   extend( baseInstance, extend)
 *   cleanCommentNode()
 *   cleanElement()
 *   getElementSize( _elm)
 *   getImageSize()
 *   getAbsolutePath()
 *   getGrobalObjectName()
 * 
 */
	var Util = ( function( window, document, undefined ){
		var body = document.getElementsByTagName( 'body' )[ 0 ];
			
		var ELM_SIZE_GETTER = ( function(){
				var ret = document.createElement( 'div' );
				body.appendChild( ret );
				
				ret.id            = 'elmSizeGetter';
				ret.style.cssText = 'position:absolute;left:0;top:-9999px;visibility:hidden';
				
				body.removeChild( ret );
				return ret;
			})(),
			CLEAN_TARGET_ELEMENT = 'script,style,object,applet,embed,iframe,frame,base,bgsound,frameset,listing'.split( ',' );
		
		var UNIT_RATIO = ( function( elm ){
				var ret = {},
					unit,
					units = 'cm,mm,in,pt,pc'.split( ',' ),
					i     = units.length;
				
				body.appendChild( elm );
				
				for( ; i; ){
					unit = units[ --i ];
					elm.style.width = 1000 + unit;
					ret[ unit ] = elm.offsetWidth / 1000;
				};
				elm.style.cssText = '';
				
				body.removeChild( elm );
				return ret;
			})( ELM_SIZE_GETTER );
			
		var FONT_SIZE_RATIO = ( function( elm ){
				var ret = {},
					size, base,
					list = 'xx-large,x-large,large,larger,medium,small,smaller,x-small,xx-small'.split( ',' ),
					i = list.length;
				
				body.appendChild( elm );
				elm.style.cssText = 'font-size:100px;line-height:1em;';
				elm.appendChild( document.createTextNode( 'X' ) );
				
				base = elm.offsetHeight;
				
				for( ; i; ){
					size = list[ --i ];
					elm.style.fontSize = size;
					ret[ size ] = base;
				};
				
				elm.style.cssText = '';
				elm.removeChild( elm.firstChild );
				body.removeChild( elm );
				return ret;
			})( ELM_SIZE_GETTER );
		
		var REG_LARGE = /[A-Z]/g;
		
		/* clean comment node */
		window.setTimeout( function(){
			// Util.cleanCommentNode();
			
			/* clean noscript */

			var noscripts = Util.copyArray( document.getElementsByTagName( 'noscript' ) ),
				ns,
				i = noscripts.length;
			for( ; i; ){
				ns = noscripts[ --i ];
				ns.parentNode && ns.parentNode.removeChild( ns );
			};
		}, 0 );
		
		var objSrc   = [],
			objCopy  = [],
			getIndex;	
		function clone( src ){
			var ret, i, key;
			if( Type.isArray(src) === true ){
				i = getIndex( objSrc, src );
				if( i !== -1 ) return objCopy[ i ];
				ret = [];
				objSrc[ objSrc.length ]   = src;
				objCopy[ objCopy.length ] = ret;
			} else
			if( Type.isObject(src) === true ){
				i = getIndex( objSrc, src );
				if( i !== -1 ) return objCopy[ i ];
				ret = {};
				objSrc[ objSrc.length ]   = src;
				objCopy[ objCopy.length ] = ret;
			} else
			if( Type.isNumber(src) === true || Type.isString(src) === true || Type.isBoolean( src ) === true ){
				return src;
			} else {
				return null;
			};
			for( key in src ){
				ret[ key ] = clone( src[ key ] );
			};
			return ret;
		};
		
		return {
			parse: function( v ){
				if( Type.isString( v ) === true ){
					if( v === 'true' )      return true;
					if( v === 'false' )     return false;
					if( v === 'null' )      return null;
					if( v === 'undefined' ) return undefined;
					if( v === 'NaN' )       return NaN;
					if( v === '' )          return v;
					var _v = v.split( ' ' ).join( '' ),
						n = _v - 0;
					if( '' + n === _v || '' + n === '0' + _v  ) return n - 0;
				};
				return v;
			},
			extend: function( target, extend ){
				for( var key in extend ){
					if( Type.isUndefined( target[ key ] ) === true ){
						target[ key ] = extend[ key ];
					} else
					if( typeof target[ key ] === typeof extend[ key ] ){
						target[ key ] = extend[ key ];
					} else {
						alert( 'extend error' );
					};
				};
				return target;
			},
			copy: function( objOrArray ){
				objSrc.length = objCopy.length = 0;
				getIndex = Util.getIndex;
				return clone( objOrArray );
			},
			cleanCommentNode: function ( _targetElm ){
				search( _targetElm || body );
				
				function search( _elm ){
					if( !_elm ) return;
					if( _elm.nodeType === 8 ){
						_elm.parentNode.removeChild( _elm );
						return;
					};
					if( _elm.nodeType === 1 ){
						var _array = Util.copyArray( _elm.childNodes ); // liveNode > array
						while( _array.length > 0 ) search( _array.shift() );
					};
				};
			},
			cleanElement: function( _targetElm ){
				var _array, _elm, j, _css,
				    i = CLEAN_TARGET_ELEMENT.length;
				for( ; i; ){
					_array = Util.copyArray( _targetElm.getElementsByTagName( CLEAN_TARGET_ELEMENT[ --i ] ) );
					for( j = _array.length; j; ){
						_elm = _nodes[ --j ];
						_elm.parentNode && _elm.parentNode.removeChild( _elm );
					};
				};
				Util.cleanCommentNode( _targetElm );
				
				if( UA.isIE === false ) return;
				_nodes = _targetElm.all || _targetElm.getElementsByTagName( '*' );
				for( i = _nodes.length; i; ){
					_elm = _nodes[ --i ];
					_css = Util.getInlineStyle( _elm );
					_css.filter   = null;
					_css.behavior = null;
					_elm.style.cssText = Util.toCssText( _css );
				};
			},
			camelize: function( cssProp ){
			    var parts = cssProp.split( ' ' ).join( '' ).split( '-' ),
			    	l     = parts.length,
			    	i, camelized;
			    if( l === 1 ) return parts[ 0 ];
			
			    camelized = cssProp.charAt(0) === '-'
			      ? parts[ 0 ].charAt( 0 ).toUpperCase() + parts[ 0 ].substring( 1 )
			      : parts[ 0 ];
			
			    for( i = 1; i < l; ++i ){
			    	camelized += parts[ i ].charAt( 0 ).toUpperCase() + parts[ i ].substring( 1 );
			    };
			    return camelized;
			},
			uncamelize: function( str ){
				return str.split( ' ' ).join( '' ).replace( REG_LARGE, '-$&' ).toLowerCase();
			},
			pxTo: function( _px, _unit ){
				return _px / ( UNIT_RATIO[ _unit ] || 1 );
			},
			toPx: function( x, _unit ){
				return x * ( UNIT_RATIO[ _unit ] || 1 );
			},
			absoluteFontSizeToPx: function( fontsize ){
				return FONT_SIZE_RATIO[ fontsize ] || 0;
			},
			getElementSize: function( _elm ){
				if( Type.isHTMLElement( _elm ) === false ){
					return {
						width:	0,
						height:	0
					};
				};
				var	parentElm   = _elm.parentNode,
					prevElm     = _elm.previousSibling,
					nextElm     = _elm.nextSibling,
					displayNone = _elm.style.display === 'none';
				if( displayNone === true ) _elm.style.display = 'block';
				
				body.appendChild( ELM_SIZE_GETTER );
				ELM_SIZE_GETTER.appendChild( _elm );
				
				var ret = {
					width:		_elm.offsetWidth,
					height:		_elm.offsetHeight
				};
				if( displayNone === true ) _elm.style.display = 'none';
				if( nextElm ){
					parentElm.insertBefore( _elm, nextElm );
				} else		
				if( prevElm && prevElm.nextSibling ){
					parentElm.insertBefore( _elm, prevElm.nextSibling );
				} else {
					parentElm && parentElm.appendChild( _elm );
				};
				body.removeChild( ELM_SIZE_GETTER );
				
				return ret;
			},
			getImageSize: function( img ){
				var	parentElm   = img.parentNode,
					prevElm     = img.previousSibling,
					nextElm     = img.nextSibling,
					displayNone = img.style.display === 'none';
				if( displayNone === true ) img.style.display = '';
				
				body.appendChild( ELM_SIZE_GETTER );
				ELM_SIZE_GETTER.appendChild( img );
				
				var size = getActualDimension( img );
				
				if( displayNone === true ) img.style.display = 'none';
				if( nextElm ){
					parentElm.insertBefore( img, nextElm );
				} else		
				if( prevElm && prevElm.nextSibling ){
					parentElm.insertBefore( img, prevElm.nextSibling );
				} else {
					parentElm && parentElm.appendChild( img );
				}
				body.removeChild( ELM_SIZE_GETTER );
				
			/* LICENSE: MIT
			 * AUTHOR: uupaa.js@gmail.com
			 */
				function getActualDimension(image) {
					var run, mem, w, h, key = "actual";
				
				// for Firefox, Safari, Google Chrome
					if( "naturalWidth" in image ){
						return {
							width:	image.naturalWidth,
							height:	image.naturalHeight
						};
					};
				
					if( "src" in image ){ // HTMLImageElement
						if (image[key] && image[key].src === image.src) {
							return image[key];
						};
						if( document.uniqueID ){ // for IE
							run = image.runtimeStyle;
							mem = { w: run.width, h: run.height }; // keep runtimeStyle
							run.width  = "auto"; // override
							run.height = "auto";
							w = image.width;
							h = image.height;
							run.width  = mem.w; // restore
							run.height = mem.h;
						} else { // for Opera and Other
							mem = { w: image.width, h: image.height }; // keep current style
							image.removeAttribute("width");
							image.removeAttribute("height");
							w = image.width;
							h = image.height;
							image.width  = mem.w; // restore
							image.height = mem.h;
						};
						return image[key] = { width: w, height: h, src: image.src }; // bond
					};
					// HTMLCanvasElement
					return { width: image.width, height: image.height };
				};
				
				return size;
			},
			getAbsolutePath: function( path ){
				var elm = document.createElement('div');
				body.appendChild( elm );
				elm.innerHTML = '<a href=\"' + path + '\" />';
				body.removeChild( elm );
				return elm.firstChild.href;
			},
			getAbsolutePosition: function( _elm ){
				// Find the destination's position
				// need html, body { fontfamily: "MS PGothic", "MS Gothic" } for ie6.
				var	destx    = _elm.offsetLeft,
					desty    = _elm.offsetTop,
					thisNode = _elm,
					body     = document.body;
				while( thisNode.offsetParent && thisNode !== body ){
					thisNode = thisNode.offsetParent;
					destx += thisNode.offsetLeft;
					desty += thisNode.offsetTop;
				};
				return {
					x:	destx,
					y:	desty
				};
			},
			contain: function( parent, child ){
				function find( node ){
					var children = node.childNodes,
						i = 0,
						l = children.length,
						elm;
					for( ; i<l; ++i ){
						elm = children[ i ];
						if( elm === child ) return true;
						if( elm.nodeType === 1 && find( elm ) === true ) return true;
					};
					return false;
				};
				return find( parent );
			},
			pullHtmlAsTemplete: function( html ){
				var elm = document.createElement( 'div' );
				body.appendChild( elm );
				elm.innerHTML = html;
				body.removeChild( elm );
				return elm.firstChild;
			},
			getElementsByClassName: function( _elm, _className, opt_tagName ){
				var _all       = !opt_tagName || opt_tagName === '*',
					_livenodes = _all === true ? ( _elm.all || _elm.getElementsByTagName( '*' )) : _elm.getElementsByTagName( opt_tagName ),
					_nodes     = Util.copyArray( _livenodes),
                    _node;
				for( var j = 0; j < _nodes.length; ){
					_node = _nodes[ j ];
					if( _node.nodeType !== 1 || Util.hasClassName( _node, _className ) === false ){
						_nodes.splice( j, 1 );
					} else {
						++j;
					};
				};
				return _nodes;
			},
			getChildIndex: function( _parent, _child ){
				var _children = _parent.getElementsByTagName( _child.tagName );
				for( var i = _children.length; i; ){
					if( _children[ --i ] === _child ) return i;
				};
				return -1;
			},
			hasClassName: function( _elm, _className ){
				var cnames  = ( _elm.className || '' ).split( ' ' ),
					_cnames = _className.split( ' ' ),
					cname,
					i = _cnames.length;
				for( ; i; ){
					cname = _cnames[ --i ];
					if( cname === '' ) continue;
					if( Util.getIndex( cnames, cname ) === -1 ) return false;
				};
				return true;
			},
			addClass: function( _elm, _className ){
				if( Util.hasClassName( _elm, _className ) === false ){
					var sp = ' ';
					var _array = ( _elm.className || '' ).replace( /\s+/g, sp ).split( sp );
					_array.push( _className );
					_elm.className = _array.join( sp );
				};
			},
			removeClass: function( _elm, _className ){
				var sp     = ' ',
					_array = _elm.className.replace( /\s+/g, sp ).split( sp ),
					i      = Util.getIndex( _array, _className );
				if( i !== -1 ){
					_array.splice( i, 1 );
					_elm.className = _array.join( sp );
				};
			},
			toggleClass: function( _elm, _className, _switch ){
				if( Type.isBoolean( _switch ) === true ){
					_switch === true ? Util.addClass( _elm, _className ) : Util.removeClass( _elm, _className );
				} else {
					Util.hasClassName( _elm, _className ) === false ? Util.addClass( _elm, _className ) : Util.removeClass( _elm, _className );
				};
			},
			removeAllChildren: function ( _elm ){
				while( _elm.firstChild ){
					remove( _elm.firstChild );
				}
				function remove( _node ){
					while( _node.firstChild){
						remove( _node.firstChild);
					}
					_node.parentNode && _node.parentNode.removeChild( _node);
				}
			},
			getIndex: function( array, element ){
				if( Array.prototype.indexof ){
					Util.getIndex = function( array, element ){
						return array.indexof( element );
					};
				} else {
					Util.getIndex = function( array, element ){
						var i = array.length;
						for( ; i; ){
							if( array[ --i ] === element ) return i;
						};
						return -1;
					};
				};
				return Util.getIndex( array, element );
			},
			copyArray: function( _array ){
				var l = _array.length,
					ret = new Array( l ),
					i = 0;
				for( ; i<l; ++i ){
					ret[ i ] = _array[ i ];
				};
				return ret;
			},
			/*
			 * 
			 */
			createGlobalUniqueName: function(){
				var randomKey = null;
				while( true ){
					randomKey = '_uniqueName'+(''+Math.random()).replace(/\./,'');
					if( typeof window[randomKey] === 'undefined'){
						break;
					}
				}
				return randomKey;
			},
			createIframe: function( id, callback, hide ){
				var ua = UA;
	            var el = document.createElement( ua.isIE ? '<iframe name="' + id + '" frameborder="0" scrolling="no">' : 'iframe');
	
	            if( ua.isIE ){
					el.onreadystatechange = function(){
		                if( this.readyState === "complete" ){
		                    this.onreadystatechange = new Function();
		                    this.onreadystatechange = null;
		                    setTimeout( asynkCallback, 0 );
		                };
		           };
	            } else {
	            	// iron(chrome) の場合、append の前に onload を指定しないと onload が呼ばれない
	            	el.onload = function(){
						el.onload = null;
						setTimeout( asynkCallback, 0 );
					};
				};
	
				document.body.appendChild( el );
	            el.id = el.name = id;
	            el.setAttribute( 'name', id );
	            if( hide === true )el.style.cssText = 'width:1px;height:1px;visibility:hidden;position:absolute;top:1px;left:1px;';
				// http://d.hatena.ne.jp/onozaty/20070830/p1
				// [JavaScript]IE6ではJavaScriptで動的に作成したiframeに対してsubmitできない(IE7は未確認) ->解決
				el.contentWindow.name = id;					
	            
	            window[ id ] = el;

				function asynkCallback(){
					callback( el );
				};
			}
		};
	})( window, document );


var CSS = ( function( window, documwnt, undefined ){
	var	CORON                  = ':',
		EMPTY                  = '',
		SEMICORON              = ';',
		UNITS                  = 'px,cm,mm,in,pt,pc,em,%'.split( ',' ),
		CLIP_SEPARATOR         = UA.isIE === true && UA.ieVersion < 8 ? ' ' : ',';

	var SPECIAL = ( function(){
		var _special = {};
		if( UA.isIE === true && UA.ieVersion < 9 ){
			if( UA.ACTIVEX === true ){
				// _special.opacity    = 'ActiveXOpacity';
				_special.setFilters = function( style ){
					var filters = ( style.filter || '' ).split( ') ' ),
						data    = {},
						i       = filters.length,
						filter, names, props, prop, j, l, key, v;
					for( ; i; ){
						filter   = filters[ --i ].split( ' ' ).join( '' ).split( '(' );
						if( filter.length !== 2 ) continue;
						names    = filter[ 0 ].split( '.' ); // progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=120,strength=9)
						props    = filter[ 1 ].split( ',' ); // 
						filter   = {};
						for( j = 0, l = props.length; j < l; ++j ){
							prop = props[ j ].split( '=' );
							key  = prop[ 0 ].toLowerCase();
							v    = prop[ 1 ];
							filter[ key ] = v; //v.charAt( 0 ) === '#' ? v : parseInt( v );
						};
						data[ names[ names.length - 1 ] ] = filter;
					};
					
					style.filter  = data;
					style.opacity = data.alpha && data.alpha.opacity ? data.alpha.opacity / 100 : 1;
				};
				_special.hasLayout = function( elm ){
					return elm.currentStyle.hasLayout;
				};
			} else {
				_special.opacity = null;
			};
		} else {
			var style = document.documentElement.style;
			_special.opacity = style.opacity          !== undefined ? 'opacity' : 
							style.MozOpacity          !== undefined ? 'MozOpacity' :
							style.KhtmlOpacity        !== undefined ? 'KhtmlOpacity' :
							style[ '-khtml-opacity' ] !== undefined ? 'KhtmlOpacity' : null;

			// if( style.backgroundPositionX === undefined ){
				_special.setBackgroundPositionXY = function( style ){
					var bgp = ( style.backgroundPosition || '' ).split( ' ' );
					style.backgroundPositionX = bgp[ 0 ] || 0;
					style.backgroundPositionY = bgp[ 1 ] || 0;
				};
			// };
			if( style.clipTop === undefined && style[ 'clip-top' ] === undefined ){
				_special.setClipTopRightBottomLeft = function( style ){
					var clip = style.clip || '';
					if( clip.indexOf( 'rect(' ) === -1 ){
						style.clipTop    = 0;
						style.clipRight  = 0;
						style.clipBottom = 0;
						style.clipLeft   = 0;
						return;
					};
					clip = clip.split( '(' )[ 1 ].split( ')' )[ 0 ].split( clip.indexOf( ',' ) !== -1 ? ',' : ' ' );
					ret.clipTop    = clip[ 0 ];
					ret.clipRight  = clip[ 1 ];
					ret.clipBottom = clip[ 2 ];
					ret.clipLeft   = clip[ 3 ];
				};
			};
		};
				
		return _special;
	})();

	var COLOR = ( function(){
		var ret = {}, v, name, i,
			list = [
				'0', 'BLACK',
				'FF0000', 'RED',
				'00FF00', 'LIME',
				'0000FF', 'BLUE',
				'FFFF00', 'YELLOW',
				'00FFFF', 'AQUA',
				'00FFFF', 'CYAN',
				'FF00FF', 'MAGENTA',
				'FF00FF', 'FUCHSIA',
				'FFFFFF', 'WHITE',
				'008000', 'GREEN',
				'800080', 'PURPLE',
				'800000', 'MAROON',
				'000080', 'NAVY',
				'808000', 'OLIVE',
				'008080', 'TEAL',
				'808080', 'GRAY',
				'C0C0C0', 'SILVER',
				'696969', 'DIMGRAY',
				'708090', 'SLATEGRAY',
				'A9A9A9', 'DARKGRAY',
				'DCDCDC', 'GAINSBORO',
				'191970', 'MIDNIGHTBLUE',
				'6A5ACD', 'SLATEBLUE',
				'0000CD', 'MEDIUMBLUE',
				'4169E1', 'ROYALBLUE',
				'1E90FF', 'DODGERBLUE',
				'87CEEB', 'SKYBLUE',
				'4682B4', 'STEELBLUE',
				'ADD8E6', 'LIGHTBLUE',
				'AFEEEE', 'PALETURQUOISE',
				'40E0D0', 'TURQUOISE',
				'E0FFFF', 'LIGHTCYAN',
				'7FFFD4', 'AQUAMARINE',
				'006400', 'DARKGREEN',
				'2E8B57', 'SEAGREEN',
				'90EE90', 'LIGHTGREEN',
				'7FFF00', 'CHARTREUSE',
				'ADFF2F', 'GREENYELLOW',
				'32CD32', 'LIMEGREEN',
				'9ACD32', 'YELLOWGREEN',
				'6B8E23', 'OLIVEDRAB',
				'BCB76B', 'DARKKHAKI',
				'EEE8AA', 'PALEGOLDENROD',
				'FFFFE0', 'LIGHTYELLOW',
				'FFD700', 'GOLD',
				'DAA520', 'GOLDENROD',
				'B8860B', 'DARKGOLDENROD',
				'BC8F8F', 'ROSYBROWN',
				'CD5C5C', 'INDIANRED',
				'8B4513', 'SADDLEBROWN',
				'A0522D', 'SIENNA',
				'CD853F', 'PERU',
				'DEB887', 'BURLYWOOD',
				'F5F5DC', 'BEIGE',
				'F5DEB3', 'WHEAT',
				'F4A460', 'SANDYBROWN',
				'D2B48C', 'TAN',
				'D2691E', 'CHOCOLATE',
				'B22222', 'FIREBRICK',
				'A52A2A', 'BROWN',
				'FA8072', 'SALMON',
				'FFA500', 'ORANGE',
				'FF7F50', 'CORAL',
				'FF6347', 'TOMATO',
				'FF69B4', 'HOTPINK',
				'FFC0CB', 'PINK',
				'FF1493', 'DEEPPINK',
				'DB7093', 'PALEVIOLETRED',
				'EE82EE', 'VIOLET',
				'DDA0DD', 'PLUM',
				'DA70D6', 'ORCHILD',
				'9400D3', 'DARKVIOLET',
				'8A2BE2', 'BLUEVIOLET',
				'9370DB', 'MEDIUMPURPLE',
				'D8BFD8', 'THISTLE',
				'E6E6FA', 'LAVENDER',
				'FFE4E1', 'MISTYROSE',
				'FFFFF0', 'IVORY',
				'FFFACD', 'LEMONCHIFFON'
			];
		for( i = list.length; i; ){
			v    = list[ --i ];
			name = list[ --i ];
			ret[ name ] = parseInt( v, 16 );
		};
		return ret;
	})();
	
	var PARAMS = ( function(){
		var ret = {};
		register( ret.percent = {},
			'marginBottom,marginLeft,marginRight,marginTop,paddingBottom,paddingLeft,paddingRight,paddingTop,fontSize,textIndent'
		);
		register( ret.offset = {},
			'height,width,bottom,left,right,top'
		);		
		register( ret.size = {},
			'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth,letterSpacing'
		);
		register( ret.color = {},
			'backgroundColor,borderBottomColor,borderLeftColor,borderRightColor,borderTopColor,color'
		);
		register( ret.region = {},
			'margin,padding,borderWidth,borderColor'
		);		
		register( ret.special = {},
			'clip,backgroundPosition,opacity,lineHeight,zIndex'
		);
		register( ret.unit = {}, 'px,cm,mm,in,pt,pc,em,%' );
		
		register( ret.margin = {}, 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom' );
		register( ret.padding = {}, 'paddingBottom,paddingLeft,paddingRight,paddingTop' );
		register( ret.borderWidth = {}, 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth' );
		register( ret.borderColor = {}, 'borderBottomColor,borderLeftColor,borderRightColor,borderTopColor' );
		
		function register( obj, params ){
			params = params.split( ',' );
			for( var i=params.length; i; ) obj[ params[ --i ] ] = true;
		};
		return ret;
	})();
	
	/*
	 * 
	 */
	var PropertyClass = function( name, value, unit, pxPerEm ){
		this.name    = name;
		this.value   = value;
		this.unit    = unit;
		this.pxPerEm = pxPerEm; // XXpx = 1em;
	};
	PropertyClass.prototype = {
		name:    '',
		value:   0,
		pxPerEm: 12, // 1em === ??px
		unit:    '',
		equal: function( prop ){
			if( this.unit === prop.unit ){
				return this.value === prop.value;
			};
			return Math.abs( this.toPx() - prop.toPx() ) < 1;
		},
		convert: function( prop ){
			var u = prop.unit, v;
			if( this.unit === u ) return;
			this.value = v = this.toPx();
			this.unit  = u;
			if( u !== px ){
				this.value = u === 'em' ? v / this.pxPerEm : Util.pxTo( v, u );
			};
		},
		setValue: function( v ){
			this.value = v;
		},
		getValue: function(){
			return this.value;
		},
		getOffset: function( prop ){
			return prop.value - this.value;
		},
		getUnit: function(){
			return this.unit;
		},
		getValueText: function(){
			return this.value === 0 ? '0' : this.value + this.unit;
		},
		clear: function(){
			var t = this, p;
			for( p in t ){
				if( t.hasOwnProperty && !t.hasOwnProperty( p ) ) continue;
				delete t[ p ];
			};
		},
		toPx: function(){
			var v = this.value, u = this.unit;
			if( u === px )   return v;
			if( u === 'em' ) return v * this.pxPerEm;
			if( u === '' && this.name === 'lineHeight' ) return v * this.pxPerEm;
			return Util.toPx( v, u );
		},
		isValid: function( t ){
			t = t || this;
			var n = t.name,
				v = t.value,
				u = t.unit,
				z = u !== '' ? true : v === 0;
			if( PARAMS.percent[ n ] === true ) return z;
			if( PARAMS.offset[ n ] === true  ) return z;
			if( PARAMS.size[ n ] === true  )   return z && u !== '%';
			if( PARAMS.special[ n ] === true  ){
				if( n === 'lineHeight' ) return true;
				if( n === 'opacity' )    return 0 <= v && v <= 1 && u === '';
				if( n === 'zIndex'  )    return u === '';
			};
			return false;
		}
	};
	
	/**
	 * backgroundPosition, clip
	 */
	var PropertyGroupClass = function( name ){
		this.name  = name;
		this.props = [];
		for( var i = 1, l = arguments.length; i<l; ++i ){
			this.props.push( arguments[ i ] );
		};
	};
	
	/**
	 * margin, padding, borderWidth, borderColor
	 */
	var FrexiblePropertyClass = function( name ){
		this.name  = name;
		this.props = [];
		for( var i = 1, l = arguments.length; i<l; ++i ){
			this.props.push( arguments[ i ] );
		};
		// top, bottom, left, right, topbottom, leftright, all
	};
	FrexiblePropertyClass.prototype = PropertyGroupClass.prototype = {
		name  : '',
		equal : function( prop ){
			var ps = this.props, i = ps.length;
			for( ; i; ){
				--i;
				if( ps[ i ].equal( prop[ i ] ) === false ) return false;
			};
			return true;
		},
		convert : function( prop ){
			var ps = this.props, i = ps.length;
			for( ; i; ){
				--i;
				ps[ i ].convert( prop[ i ] );
			};
		},
		setValue : function( ary ){
			var ps = this.props, i = 0, l = ps.length;
			for( ; i<l; ++i ){
				ps[ i ].setValue( ary[ i ] );
			};
		},
		getValue : function(){
			var ret = [], ps = this.props, i = 0, l = ps.length;
			for( ; i<l; ++i ){
				ret.push( ps[ i ].getValue() );
			};
			return ret;
		},
		getOffset : function( prop ){
			var ret = [],
				ps  = this.props,
				_ps = prop.props,
				i   = 0,
				l = ps.length;
			for( ; i<l; ++i ){
				ret.push( ps[ i ].getOffset( _ps[ i ] ) );
			};
			return ret;
		},
		getUnit : function(){
			var ret = [], ps = this.props, i = 0, l = ps.length;
			for( ; i<l; ++i ){
				ret.push( ps[ i ].getUnit() );
			};
			return ret;
		},
		getValueText : function(){
			var ret = [], ps = this.props, i = 0, l = ps.length;
			for( ; i<l; ++i ){
				ret.push( ps[ i ].getValueText() );
			};			
			if( this.name === 'clip' ){
				return 'rect(' + ret.join( CLIP_SEPARATOR ) + ')';
			};
			return ret.join( ' ' );
		},
		clear : function(){
			var ps = this.props, i = ps.length;
			for( ; i; ){
				ps[ --i ].clear();
			};
			delete this.name;
			delete this.props;
		},
		isValid : function( t ){
			t = t || this;
			var ps = t.props, i = ps.length;
			for( ; i; ){
				--i;
				if( ps[ i ].isValid() === false ) return false;
			};
			return true;
		}
	};

	var ColorPropertyClass = function( name, r, g, b, pct ){
		this.name = name;
		this.r    = r;
		this.g    = g;
		this.b    = b;
		this.pct  = pct;
	};
	ColorPropertyClass.prototype = {
		name  : '',
		equal : function( prop ){
			if( this.pct === prop.pct ){
				return this.r === prop.r && this.g === prop.g && this.b === prop.b;
			};
			var rgb  = this._toPct(),
				_rgb = prop._toPct(),
				i    = rgb.length;
			for( ; i; ){
				--i;
				if( Math.abs( rgb[ i ] - _rgb[ i ] ) > 1 ) return false;
			};
			return true;
		},
		convert : function( prop ){
			var u = prop.pct, x;
			if( this.pct === u ) return;
			x = u === true ? 100 / 255 : 2.55;
			this.r  *= x;
			this.g  *= x;
			this.b  *= x;
			this.pct = u;
		},
		setValue : function( rgb ){
			this.r = rgb[ 0 ];
			this.g = rgb[ 1 ];
			this.b = rgb[ 2 ];
		},
		getValue : function(){
			return [ this.r, this.g, this.b ];
		},
		getOffset : function( prop ){
			return [ prop.r - this.r, prop.g - this.g, prop.b - this.b ];
		},
		getUnit : function(){
			return this.pct === true ? '%' : '';
		},
		getValueText : function(){
			if( this.pct === true ){
				return [ 'rgb(', this.r, '%,', this.g, '%,', this.b, '%)' ].join( '' );
			};
			var round = Math.round;
			//return [ 'rgb(', round( this.r ), ',', round( this.g ), ',', round( this.b ), ')' ].join( '' );
			
			var rgb   = '00000' + ( ( round( this.r ) << 16 ) + ( round( this.g ) << 8 ) + round( this.b ) ).toString( 16 );
			return '#' + rgb.substr( rgb.length - 6 );
		},
		clear : function(){
			var t = this, p;
			for( p in t ){
				if( t.hasOwnProperty && !t.hasOwnProperty( p ) ) continue;
				delete t[ p ];
			};
		},
		_toPct : function(){
			if( this.pct === true ) return [ this.r, this.g, this.b ];
			return [ this.r / 2.55, this.g / 2.55, this.b / 2.55 ];
		},
		isValid : function( t ){
			var isFinite = window.isFinite;
			if( !isFinite( this.r ) || !isFinite( this.g ) || !isFinite( this.b ) ) return false;
			if( 0 > this.r || 0 > this.g || 0 > this.b ) return false;
			if( this.pct === true ){
				return this.r <= 100 && this.g <= 100 && this.b <= 100;
			};
			return this.r <= 255 && this.g <= 255 && this.b <= 255;
		}
	};
	
	var isString       = Type.isString,
		isNumber       = Type.isNumber;
	var REG_UINIT      = /.*\d(\w{1,2})?/,
		$1             = '$1',
		px             = 'px',
		REG_XXXXXX     = /^#[\da-fA-F]{6}?/,
		REG_XXX        = /^#[\da-fA-F]{3}?/;
	
	var WrappedStyleClass = function( elm, style ){
		this.elm     = elm;
		this.style   = style;
		this.pxPerEm = this.get( 'fontSize' ).toPx();
	};

	WrappedStyleClass.prototype = {
		get: function( p ){
			if( PARAMS.special[ p ] === true || PARAMS.region[ p ] === true ){
				if( p === 'clip' )        return this.getClip();
				if( p === 'margin' )      return this.getMarginPaddingBorder( p );
				if( p === 'padding' )     return this.getMarginPaddingBorder( p );
				if( p === 'borderWidth' ) return this.getMarginPaddingBorder( 'border', 'Width' );
				if( p === 'borderColor' ) return this.getBorderColor( 'borderColor' );
				if( p === 'backgroundPosition' ) return this.getBackgroundPosition( p );
				// opacity, zindex, lineHeight
				return new PropertyClass( p, this.getValue( x, p ), this.getUnit( x ), this.pxPerEm );
			};
			var x = this.style[ p ], e, v, u;
			if( PARAMS.offset[ p ] === true ){
				return new PropertyClass( p, this.getValue( x, p ), this.getUnit( x, p ), this.pxPerEm );
				/*
				e = this.elm;
				if( p === 'width'  ) v = e.offsetWidth;
				if( p === 'height' ) v = e.offsetHeight;
				if( p === 'top'    ) v = e.offsetTop;
				if( p === 'bottom' ) v = e.offsetBottom;
				if( p === 'left'   ) v = e.offsetLeft;
				if( p === 'right'  ) v = e.offsetRight;
				u = this.getUnit( x, p );
				// alert( p + this.pxTo( v, u ) + u )
				return new PropertyClass( p, this.pxTo( v, u ), u, this.pxPerEm ); */
			};
			if( p === 'fontSize' ){ // xx-small 等
				v = Util.absoluteFontSizeToPx( x );
				if( v !== 0 ){
					return new PropertyClass( p, v, px, this.pxPerEm );
				};
			};			
			if( PARAMS.percent[ p ] === true ){
				// alert( p + ' , ' + x + ' , ' + this.getUnit( x, p ) )
				return new PropertyClass( p, this.getValue( x, p ), this.getUnit( x, p ), this.pxPerEm );
			};
			if( PARAMS.size[ p ] === true ){
				return new PropertyClass( p, this.getValue( x, p ), this.getUnit( x, p ), this.pxPerEm );
			};
			if( PARAMS.color[ p ] === true ){
				return this.getColor( x, p );
			};
		},
		pxTo: function( px, unit ){
			if( unit === 'em' ) return px / this.pxPerEm;
			return Util.pxTo( px, unit );
		},
		getValue: function( x, p ){
			if( isString( x ) === true ){
				return parseInt( x );
			} else
			if( isNumber( x ) === true ){
				return x;
			};
			return 0;
		},
		getUnit: function( x, p ){
			var u;
			if( isString( x ) === true ){
				u = x.replace( REG_UINIT, $1 );
				if( p === 'lineHeight' ) return u;
				if( PARAMS.unit[ u ] !== true ) return px;
				return u;
			};
			return px;
		},
		getColor: function( x, p ){
			var rgb = COLOR[ x.toUpperCase() ],
				pct = false,
				r   = 0,
				g   = 0,
				b   = 0;
			if( isNumber( rgb ) === true ){
				r = ( rgb & 0xff0000 ) >> 16;
				g = ( rgb & 0xff00 ) >> 8;
				b = ( rgb & 0xff );
			} else
			if( x.match( REG_XXXXXX ) ){
				r = parseInt( x.charAt( 1 ) + x.charAt( 2 ), 16 );
				g = parseInt( x.charAt( 3 ) + x.charAt( 4 ), 16 );
				b = parseInt( x.charAt( 5 ) + x.charAt( 6 ), 16 );
				//alert( x + ' g: ' + g )
			} else			
			if( x.match( REG_XXX ) ){
				r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
				g = parseInt( x.charAt( 2 ) + x.charAt( 2 ), 16 );
				b = parseInt( x.charAt( 3 ) + x.charAt( 3 ), 16 );
			} else
			if( x.indexOf( 'rgb(' ) === 0 ){
				rgb = x.substr( 4 ).split( ',' );
				r = parseFloat( rgb[ 0 ] );
				g = parseFloat( rgb[ 1 ] );
				b = parseFloat( rgb[ 2 ] );
				if( x.indexOf( '%' ) !== -1 ){
					pct = true;
				};
			} else {
				r = 255;
				g = 255;
				b = 255;
			};
			return new ColorPropertyClass( p, r, g, b, pct );
		},
		getClip: function( name ){
			// rect(...)	クリップします。<top>, <bottom> は上端からの、 <right>, <left> は左端からのオフセットで指定します。Internet Explorer 4～7 では、カンマの代わりにスペースで区切る必要があります。
			// position:absolute または position:fixed を適用した要素に対してのみ有効です。
			var top    = this.get( name + 'Top' ),
				right  = this.get( name + 'Right' ),
				bottom = this.get( name + 'Bottom' ),
				left   = this.get( name + 'Left' ),
				ret    = new PropertyGroupClass( name, top, right, bottom, left),
                all;
			if( ret.isValid() === true ) return ret;
			ret.clear();
			all    = this.style[ name ].split( '(' )[ 1 ].split( ')' )[ 0 ].split( CLIP_SEPARATOR );
			return new PropertyGroupClass( name,
				new PropertyClass( name + 'Top',    all[ 0 ], px, this.pxPerEm ),
				new PropertyClass( name + 'Right',  all[ 1 ], px, this.pxPerEm ),
				new PropertyClass( name + 'Bottom', all[ 2 ], px, this.pxPerEm ),
				new PropertyClass( name + 'Left',   all[ 3 ], px, this.pxPerEm )
			);
		},
		getBackgroundPosition: function( name ){
			var x   = this.get( name + 'X' ),
				y   = this.get( name + 'Y' ),
				ret = new PropertyGroupClass( name, x, y ),
				xy;
			if( ret.isValid() === true ) return ret;
			ret.clear();
			xy  = this.style[ name ].split( ' ' );
			return new PropertyGroupClass( name,
				new PropertyClass( name + 'X', this.getValue( xy[ 0 ] ), this.getUnit( xy[ 0 ] ), this.pxPerEm ),
				new PropertyClass( name + 'Y', this.getValue( xy[ 1 ] ), this.getUnit( xy[ 1 ] ), this.pxPerEm )
			);
		},
		getMarginPaddingBorder: function( name, widthOrColor ){
			widthOrColor = widthOrColor || '';
			var _class = PropertyClass,
				top    = this.get( name + 'Top' + widthOrColor ),
				right  = this.get( name + 'Right' + widthOrColor ),
				bottom = this.get( name + 'Bottom' + widthOrColor ),
				left   = this.get( name + 'Left' + widthOrColor ),
				ret    = new FrexiblePropertyClass( name, top, right, bottom, left ),
				all, x, v, u, i, l;
			
			if( ret.isValid() === true ) return ret;
			ret.clear();
			all = this.style[ name + widthOrColor ].split( ' ' );
			
			for( i = 0, l=all.length; i<l; ++i ){
				x = all[ i ];
				v = this.getValue( x );
				u = this.getUnit( x );
				if( l === 4 ){
					if( i === 0 ) top    = new _class( name + 'Top' +    widthOrColor, v, u, this.pxPerEm );
					if( i === 1 ) right  = new _class( name + 'Right' +  widthOrColor, v, u, this.pxPerEm );
					if( i === 2 ) bottom = new _class( name + 'Bottom' + widthOrColor, v, u, this.pxPerEm );
					if( i === 3 ) left   = new _class( name + 'Left' +   widthOrColor, v, u, this.pxPerEm );
				} else
				if( l === 3 ){
					if( i === 0 ) top    = new _class( name + 'Top' + widthOrColor, v, u, this.pxPerEm );
					if( i === 1 ){
						right  = new _class( name + 'Right' + widthOrColor, v, u, this.pxPerEm );
						left   = new _class( name + 'Left'  + widthOrColor, v, u, this.pxPerEm );
					} else
					if( i === 2 ) bottom = new _class( name + 'Bottom' + widthOrColor , v, u, this.pxPerEm );
				} else
				if( l === 2 ){
					if( i === 0 ){
						top    = new _class( name + 'Top'    + widthOrColor, v, u, this.pxPerEm );
						bottom = new _class( name + 'Bottom' + widthOrColor, v, u, this.pxPerEm );
					} else
					if( i === 1 ){
						right  = new _class( name + 'Right' + widthOrColor, v, u, this.pxPerEm );
						left   = new _class( name + 'Left'  + widthOrColor, v, u, this.pxPerEm );
					};
				} else
				if( l === 1 ){
					top    = new _class( name + 'Top'    + widthOrColor, v, u, this.pxPerEm );
					bottom = new _class( name + 'Bottom' + widthOrColor, v, u, this.pxPerEm );
					right  = new _class( name + 'Right'  + widthOrColor, v, u, this.pxPerEm );
					left   = new _class( name + 'Left'   + widthOrColor, v, u, this.pxPerEm );
				};
			};
			return new FrexiblePropertyClass( name, top, right, bottom, left );
		},
		getBorderColor: function( name ){
			var getColor = this.getColor,
				top      = this.get( name + 'TopColor' ),
				right    = this.get( name + 'RightColor' ),
				bottom   = this.get( name + 'BottomColor' ),
				left     = this.get( name + 'LeftColor' ),
				ret      = new FrexiblePropertyClass( name, top, right, bottom, left ),
				all, x, i, l;
			
			if( ret.isValid() === true ) return ret;
			ret.clear();
			all = this.style[ name ].split( ' ' );
			
			for( i = 0, l = all.length; i<l; ++i ){
				x = all[ i ];
				if( l === 4 ){
					if( i === 0 ) top    = getColor( x, name + 'Top' );
					if( i === 1 ) right  = getColor( x, name + 'Right' );
					if( i === 2 ) bottom = getColor( x, name + 'Bottom' );
					if( i === 3 ) left   = getColor( x, name + 'Left' );
				} else
				if( l === 3 ){
					if( i === 0 ) top    = getColor( x, name + 'Top' );
					if( i === 1 ){
						right  = getColor( x, name + 'Right' );
						left   = getColor( x, name + 'Left' );
					} else
					if( i === 2 ) bottom = getColor( x, name + 'Bottom' );
				} else
				if( l === 2 ){
					if( i === 0 ){
						top    = getColor( x, name + 'Top' );
						bottom = getColor( x, name + 'Bottom' );
					} else
					if( i === 1 ){
						right  = getColor( x, name + 'Right' );
						left   = getColor( x, name + 'Left' );
					};
				} else
				if( l === 1 ){
					top    = getColor( x, name + 'Top' );
					bottom = getColor( x, name + 'Bottom' );
					right  = getColor( x, name + 'Right' );
					left   = getColor( x, name + 'Left' );
				};
			};
			return new FrexiblePropertyClass( name, top, right, bottom, left );
		},
		clear: function(){
			var t = this, p;
			for( p in t ){
				if( t.hasOwnProperty && !t.hasOwnProperty( p ) ) continue;
				delete t[ p ];
			};
		}
	};
	function camelizeHash( obj ){
		var p, _p;
		for( p in obj ){
			_p = Util.camelize( p );
			if( _p === p ) continue;
			obj[ _p ] = obj[ _p ] || obj[ p ];
			delete obj[ p ];
		};
		return obj;
	};
	function cssToObject( css ){
		var ret      = {}, i, nv, n, v,
			parse    = Util.parse,
			isNumber = Type.isNumber,
			camelize = Util.camelize;
		if( Type.isString( css ) === true ){
			css = css.split( ';' );
			for( i = css.length; i; ){
				nv    = css[ --i ].split( ':' ); // filter の場合, progid: がくる
				n     = nv.shift();
				if( isNumber( parse( n ) ) === true ) continue;
				v     = nv.join( '' );
				while( v.charAt( 0 ) === ' ' ) v = v.substr( 1 );
				ret[ camelize( n ) ] = parse( v );
			};
		} else {
			for( n in css ){
				if( Type.isNumber( parse( n ) ) === false ) ret[ n ] = parse( css[ n ] );
			};
		};

		if( SPECIAL.setFilters ){
			SPECIAL.setFilters( ret );
		} else {
			ret.opacity = SPECIAL.opacity !== null ? ret[ SPECIAL.opacity ] : 1;
		};
		
		SPECIAL.setBackgroundPositionXY && SPECIAL.setBackgroundPositionXY( ret );
		SPECIAL.setClipTopRightBottomLeft && SPECIAL.setClipTopRightBottomLeft( ret );
		
		return ret;
	};
	return {
		getWrappedStyle: function( elm, opt_css ){
			return new WrappedStyleClass( elm, opt_css ? camelizeHash( opt_css ) : CSS.getComputedStyle( elm ) );
		},
		getInlineStyle: function( _elm ){
			return cssToObject( _elm.style.cssText );
		},
		getStyleProperty : function( elm, property ){
		    if( document.defaultView && document.defaultView.getComputedStyle ){
		        CSS.getStyleProperty = function( elm, property ){
		        	var obj      = document.defaultView.getComputedStyle( elm, '' ),
		        		style    = {},
		        		wrapped,
		        		fontSize = 'fontSize',
		        		number   = PARAMS.percent[ property ] || PARAMS.offset[ property ] || PARAMS.size[ property ] || PARAMS.color[ property ] || PARAMS.region[ property ] || PARAMS.special[ property ],
		        		css, nv, n, v, i;
		        		
		        	if( obj.cssText ){
						css = obj.cssText.split( ';' );
						for( i = css.length; i; ){
							nv = css[ --i ].split( ':' ); // filter の場合, progid: がくる
							n  = Util.camelize( nv.shift() );
							if( n === property && number === false ) return nv.join( '' );
							if( n === property || n === fontSize ){
								v = nv.join( '' );
								while( v.charAt( 0 ) === ' ' ) v = v.substr( 1 );
								style[ n ] = v;
								if( style[ property ] && style[ fontSize ] ) break;
							};
						};
		        	} else {
		        		if( number === false ) return obj[ property ];
		        		
		        		style[ property ] = obj[ property ];
		        		if( !style[ property ] ) style[ property ] = obj[ Util.uncamelize( property ) ];
		        		style[ fontSize ] = obj[ fontSize ];
		        		if( !style[ fontSize ] ) style[ fontSize ] = obj[ Util.uncamelize( fontSize ) ];
		        	};
		        	
		        	wrapped = CSS.getWrappedStyle( elm, style );
		        	
		        	return wrapped.get( property );
		        };
		    } else {
		        CSS.getStyleProperty = function( elm, property ){
		        	var obj      = elm.currentStyle,
		        		style    = {},
		        		wrapped,
		        		fontSize = 'fontSize',
		        		number   = PARAMS.percent[ property ] || PARAMS.offset[ property ] || PARAMS.size[ property ] || PARAMS.color[ property ] || PARAMS.region[ property ] || PARAMS.special[ property ];
	        		if( number === false ) return obj[ property ];
	        		
	        		style[ property ] = obj[ property ];
	        		if( !style[ property ] ) style[ property ] = obj[ Util.uncamelize( property ) ];
	        		style[ fontSize ] = obj[ fontSize ];
	        		if( !style[ fontSize ] ) style[ fontSize ] = obj[ Util.uncamelize( fontSize ) ];
		        	
		        	wrapped = CSS.getWrappedStyle( elm, style );
		        	
		        	return wrapped.get( property );
		        };
		    };
		    return CSS.getStyleProperty( elm, property );
		},
		getComputedStyle: function( elm ){
			/* if( window.getComputedStyle ){
		        CSS.getComputedStyle = function( elm ){
		        	return cssToObject( window.getComputedStyle( elm, '' ) );
		        };
		  	} else */
		    if( document.defaultView && document.defaultView.getComputedStyle ){
		        CSS.getComputedStyle = function( elm ){
		        	var obj = document.defaultView.getComputedStyle( elm, '' );
		        	return cssToObject( obj.cssText || obj );
		        };
		    } else {
		        CSS.getComputedStyle = function( elm ){
		        	return cssToObject( elm.currentStyle );
		        };
		    };
		    return CSS.getComputedStyle( elm );
		},
		toCssText: function( _css ){
			var ret = [], v;
			for( var p in _css ){
				if( PARAMS.margin[ p ] === true && _css.margin ) continue;
				if( PARAMS.padding[ p ] === true && _css.padding ) continue;
				if( PARAMS.borderWidth[ p ] === true && _css.borderWidth ) continue;
				if( PARAMS.borderColor[ p ] === true && _css.borderColor ) continue;
				v = _css[ p ];
				v && ret.push( [ Util.uncamelize( p ), v ].join( ':' ) );
			};
			return ret.join( ';' );
		}
	};
	
})( window, document );



/* original:
 *   susie-t, http://d.hatena.ne.jp/susie-t/20070218/1171760841
 */
var Position = {
	positionedOffset : function( element ){
		var valueT  = 0,
			valueL  = 0,
			include = Position.isIncludeBorder,
			minus   = Position.isMinusBodyBorder,
			body    = document.body,
			parent, border, p;
		do {
			valueT += element.offsetTop || 0;
			valueL += element.offsetLeft || 0;
			parent  = element.offsetParent;
			if( !include ){
				border  = Position.getBorder( parent );
				valueT += border[0];
				valueL += border[1];
				if( parent === body && minus ){
					valueT += border[0];
					valueL += border[1];
				};
			};
			if( parent === body ) break;
			if( parent ){
				p = CSS.getStyleProperty( parent, 'position' );
				// p = CSS.getComputedStyle( parent ).position;
				if( p === 'relative' || p === 'absolute' ) break;
			};
		} while( element = parent );
		return [ valueL, valueT ];
	},
	page : function( forElement ){
		var valueT  = 0,
			valueL  = 0,
			include = Position.isIncludeBorder,
			minus   = Position.isMinusBodyBorder,
			body    = document.body,
			element = forElement,
			parent, border;
		do {
			valueT += element.offsetTop || 0;
			valueL += element.offsetLeft || 0;
			parent  = element.offsetParent;
			if( !include ){
				border  = Position.getBorder( parent );
				valueT += border[1];
				valueL += border[0];
				if( parent === body && minus ){
					valueT += border[0];
					valueL += border[1];
				};
			};
			// Safari fix
			if( parent === body && CSS.getStyleProperty( element, 'position' ) === 'absolute' ){
				break;	
			};
		} while( element = parent );

		element = forElement;
		do {
			valueT -= element.scrollTop || 0;
			valueL -= element.scrollLeft || 0;
		} while( element = element.parentNode );

		return [ valueL, valueT ];
	},
	getBorder : function( element ){
		if( element === null ){
			return [ 0, 0 ];
		};
		/**
		var top        = 0,
			left       = 0,
			dhtmlStyle = CSS.getWrappedStyle( element );
			compStyle  = CSS.getComputedStyle( element );
		if( compStyle.borderTopStyle !== 'none' ){
			top = dhtmlStyle.get( 'borderTopWidth' ).toPx();//parseInt( Element.getStyle( element, 'border-top-width' ) );
		};
		if( compStyle.borderLeftStyle !== 'none' ){
			left = dhtmlStyle.get( 'borderLeftWidth' ).toPx();//parseInt( Element.getStyle( element, 'border-left-width' ) );
		};
		*/
		var top        = 0,
			left       = 0;
		if( CSS.getStyleProperty( element, 'borderTopStyle' ) !== 'none' ){
			top  = CSS.getStyleProperty( element, 'borderTopWidth' ).toPx();
		};
		if( CSS.getStyleProperty( element, 'borderLeftStyle' ) !== 'none' ){
			left = CSS.getStyleProperty( element, 'borderLeftWidth' ).toPx();
		};
		
		return [ left || 0, top || 0 ];
	},
	isIncludeBorder : ( function() {
		var parent = document.createElement( 'div' );
		document.body.appendChild( parent );
		parent.style.cssText = 'border:solid blue 10px; padding:0px; position:absolute; visibility:hidden;';
		
		var child  = document.createElement( 'div' );
		parent.appendChild( child );
		var ret = child.offsetTop === 0 ? false : true;

		document.body.removeChild( parent );

		return ret;
	})(),
	isMinusBodyBorder : ( function(){
		return document.body.offsetTop < CSS.getWrappedStyle( document.body ).get( 'marginTop' ).toPx();
		// return document.body.offsetTop < CSS.getStyleProperty( document.body, 'marginTop' ).toPx();	
	})(),
	cumulativeOffset : function( element ){
		if( /Konqueror|Safari|KHTML/.test( navigator.userAgent ) ){
			Position.cumulativeOffset = function( element ){
				var valueT  = 0,
					valueL  = 0,
					include = Position.isIncludeBorder,
					minus   = Position.isMinusBodyBorder,
					body    = document.body,
					parent, border;
				do {
					valueT += element.offsetTop || 0;
					valueL += element.offsetLeft || 0;
					parent  = element.offsetParent;
					if( !include ){
						border = Position.getBorder( parent );
						valueT += border[1];
						valueL += border[0];
						if( parent === body && minus ){
							valueT += border[0];
							valueL += border[1];
						};
					};
					if( parent === body && CSS.getStyleProperty( element, 'position' ) === 'absolute' ){
						break;	
					};
					element = parent;
				} while ( element );
		
				return [ valueL, valueT ];
			};
		} else {
			Position.cumulativeOffset = function( element ){
				var valueT  = 0,
					valueL  = 0,
					include = Position.isIncludeBorder,
					minus   = Position.isMinusBodyBorder,
					body    = document.body,
					parent, border;
				do {
					valueT += element.offsetTop || 0;
					valueL += element.offsetLeft || 0;
					parent  = element.offsetParent;
					if( !include ){
						border  = Position.getBorder( parent );
						valueT += border[1];
						valueL += border[0];
						if( parent === body && minus ){
							valueT += border[0];
							valueL += border[1];
						};
					};
					element = parent;
				} while( element );
				return [ valueL, valueT ];
			};			
		};
		return Position.cumulativeOffset( element );
	}
};


