var BoxModel;

var DOM = ( function( window, document ){
	var DIV_LIST  = [],
		SPAN_LIST = [],
		TEXT_LIST = [];
	
	var elmTextSize;
	
	function correctNodes( node ){
		var child;
		if( node && node.parentNode ){
			while( node.lastChild ) correctNodes( node.lastChild );
			node.parentNode.removeChild( node );
			if( node.nodeType === 1 ){
				switch( node.tagName ){
					case 'DIV':
						DIV_LIST.push( node );
						break;
					case 'SPAN':
						SPAN_LIST.push( node );
						break;
					
				};
				node.removeAttribute( 'className' );
				node.removeAttribute( 'style' );
				node.removeAttribute( 'id' );
			} else
			if( node.nodeType === 3 ){
				node.data = '';
				TEXT_LIST.push( node );
			};
		};
	};
	
	return {
		createDiv : function(){
			return 0 < DIV_LIST.length ? DIV_LIST.shift() : document.createElement( 'div' );
		},
		createSpan : function(){
			
		},
		createText : function(){
			
		},
		getTextSize : function( elm, content ){
			var span = DOM.createSpan(),
				text = DOM.createText(),
				w, h;
			elm.appendChild( span );
			span.style.cssText = 'visibility:hidden;position:absolute;';
			span.appendChild( text );
			text.data = content;
			w = span.offsetWidth;
			h = span.offsetHeight;
			DOM.correctNodes( span );
			return [ w, h ];
		},
		getTextHeight : function( elm, w, content ){
			var div  = DOM.createSpan(),
				text = DOM.createText(),
				w, h;
			elm.appendChild( div );
			div.style.cssText = 'visibility:hidden;position:absolute;width:' + w + 'px;';
			div.appendChild( text );
			text.data = content;
			w = div.offsetWidth;
			h = div.offsetHeight;
			DOM.correctNodes( div );
			return h;
		},
		correctNodes : function( node ){
			var child;
			if( node && node.parentNode ){
				while( node.lastChild ) DOM.correctNodes( node.lastChild );
				node.parentNode.removeChild( node );
				if( node.nodeType === 1 ){
					switch( node.tagName ){
						case 'DIV':
							DIV_LIST.push( node );
							break;
						case 'SPAN':
							SPAN_LIST.push( node );
							break;
						
					};
					node.removeAttribute( 'className' );
					node.removeAttribute( 'style' );
					node.removeAttribute( 'id' );
				} else
				if( node.nodeType === 3 ){
					node.data = '';
					TEXT_LIST.push( node );
				};
			};
		}
	}
})( window, document );

var XBrowserStyle = ( function(){
	var	EMPTY          = '',
		CORON          = ':',
		SEMICORON      = ';',
		SPACE          = ' ',
		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( !cliop || 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;
	})();
	
	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( SEMICORON );
			for( i = css.length; i; ){
				nv = css[ --i ].split( CORON ); // filter の場合, progid: がくる
				n  = nv.shift();
				if( isNumber( parse( n ) ) === true ) continue;
				v  = nv.join( EMPTY );
				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;
	};

	var COLOR = ( function(){
		var ret = {}, v, name,
			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 Property = Class.create(
		'Property',
		Class.POOL_OBJECT,
		{
			Constructor : function( name, value, unit, pxPerEm ){
				this.name    = name;
				this.value   = value;
				this.unit    = unit;
				this.pxPerEm = pxPerEm; // XXpx = 1em;
			},
			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;
			},
			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 PropertyGroup = Class.create(
		'PropertyGroup',
		Class.POOL_OBJECT,
		{
			Constructor : function( name ){
				this.name  = name;
				this.props = [];
				for( var i = 1, l = arguments.length; i<l; ++i ){
					this.props.push( arguments[ i ] );
				};
			},
			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( ' ' );
			},
			onKill : function(){
				var ps = this.props, i = ps.length;
				for( ; i; ){
					ps[ --i ].kill();
				};
			},
			isValid : function( t ){
				t = t || this;
				var ps = t.props, i = ps.length;
				for( ; i; ){
					if( ps[ --i ].isValid() === false ) return false;
				};
				return true;
			}
		}
	);
	
	/**
	 * margin, padding, borderWidth, borderColor
	 */
	var FrexibleProperty = PropertyGroup.inherits(
		'FrexibleProperty',
		Class.POOL_OBJECT, {
			Constructor : 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				
			}
		}
	);

	var ColorProperty = Class.create(
		'ColorProperty',
		Class.POOL_OBJECT, {
			Constructor : function( name, r, g, b, pct ){
				this.name = name;
				this.r    = r;
				this.g    = g;
				this.b    = b;
				this.pct  = pct;
			},
			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 );
			},
			_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 WrappedStyle = Class.create(
		'WrappedStyle',
		Class.POOL_OBJECT,
		{
			Constructor : function( style ){
				this.style   = style;
				var fontsize = this.get( 'fontSize' );
				this.pxPerEm = fontsize.toPx();
				fonstsize.kill();
			},
			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 Property( p, this.getValue( x ), this.getUnit( x ), this.pxPerEm );
				};
				var x = this.style[ p ], e, v, u;
				if( PARAMS.offset[ p ] === true ){
					return new Property( p, this.getValue( x ), 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 Property( p, this.pxTo( v, u ), u, this.pxPerEm ); */
				};
				if( p === 'fontSize' ){ // xx-small 等
					v = Util.absoluteFontSizeToPx( x );
					if( v !== 0 ){
						return new Property( p, v, px, this.pxPerEm );
					};
				};			
				if( PARAMS.percent[ p ] === true ){
					// alert( p + ' , ' + x + ' , ' + this.getUnit( x, p ) )
					return new Property( p, this.getValue( x ), this.getUnit( x, p ), this.pxPerEm );
				};
				if( PARAMS.size[ p ] === true ){
					return new Property( p, this.getValue( x ), 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 ){
				return isString( x ) === true ? parseInt( x ) :
				       isNumber( x ) === true ? x : 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 ColorProperty( 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 PropertyGroup( name, top, right, bottom, left),
                    all;
				if( ret.isValid() === true ) return ret;
				ret.kill();
				all    = this.style[ name ].split( '(' )[ 1 ].split( ')' )[ 0 ].split( CLIP_SEPARATOR );
				return new PropertyGroup( name,
					new Property( name + 'Top',    all[ 0 ], px, this.pxPerEm ),
					new Property( name + 'Right',  all[ 1 ], px, this.pxPerEm ),
					new Property( name + 'Bottom', all[ 2 ], px, this.pxPerEm ),
					new Property( name + 'Left',   all[ 3 ], px, this.pxPerEm )
				);
			},
			getBackgroundPosition: function( name ){
				var x   = this.get( name + 'X' ),
					y   = this.get( name + 'Y' ),
					ret = new PropertyGroup( name, x, y ),
					xy;
				if( ret.isValid() === true ) return ret;
				ret.kill();
				xy  = this.style[ name ].split( ' ' );
				return new PropertyGroup( name,
					new Property( name + 'X', this.getValue( xy[ 0 ] ), this.getUnit( xy[ 0 ] ), this.pxPerEm ),
					new Property( name + 'Y', this.getValue( xy[ 1 ] ), this.getUnit( xy[ 1 ] ), this.pxPerEm )
				);
			},
			getMarginPaddingBorder: function( name, width ){
				var props  = [ name + 'Top'    + width,
					           name + 'Right'  + width,
					           name + 'Bottom' + width,
					           name + 'Left'   + width ],
					top    = this.get( props[ 0 ] ),
					right  = this.get( props[ 1 ] ),
					bottom = this.get( props[ 2 ] ),
					left   = this.get( props[ 3 ] ),
					ret    = new FrexibleProperty( name, top, right, bottom, left ),
					klass, pxPerEm, getValue, getUnit,
					all, _0, _1, _2, _3, v, u;
				if( ret.isValid() === true ) return ret;
				ret.kill();
				klass    = Property;
				pxPerEm  = this.pxPerEm;
				getValue = this.getValue;
				getUnit  = this.getUnit;
				all = this.style[ name + width ].split( ' ' );
				_0 = all[ 0 ];
				_1 = all[ 1 ];
				_2 = all[ 2 ];
				_3 = all[ 3 ];
				v  = getValue( _0 );
				u  = getUnit( _0 );
				switch( all.length ){
					case 1 :
						top    = new klass( props[ 0 ], v, u, pxPerEm );
						right  = new klass( props[ 1 ], v, u, pxPerEm );
						bottom = new klass( props[ 2 ], v, u, pxPerEm );
						left   = new klass( props[ 3 ], v, u, pxPerEm );
						break;
					case 2 :
						top    = new klass( props[ 0 ], v, u, pxPerEm );
						bottom = new klass( props[ 2 ], v, u, pxPerEm );
						v  = getValue( _1 );
						u  = getUnit( _1 );
						right  = new klass( props[ 1 ], v, u, pxPerEm );
						left   = new klass( props[ 3 ], v, u, pxPerEm );
						break;
					case 3 :
						top    = new klass( props[ 0 ], v, u, pxPerEm );
						v  = getValue( _1 );
						u  = getUnit( _1 );
						right  = new klass( props[ 1 ], v, u, pxPerEm );
						left   = new klass( props[ 3 ], v, u, pxPerEm );
						bottom = new klass( props[ 2 ], getValue( _2 ), getUnit( _2 ), pxPerEm );
						break;
					case 4 :
						top    = new klass( props[ 0 ], v, u, pxPerEm );
						right  = new klass( props[ 1 ], getValue( _1 ), getUnit( _1 ), pxPerEm );
						bottom = new klass( props[ 2 ], getValue( _2 ), getUnit( _2 ), pxPerEm );
						left   = new klass( props[ 3 ], getValue( _3 ), getUnit( _3 ), pxPerEm );
						break;
				};
				return new FrexibleProperty( name, top, right, bottom, left );
			},
			getBorderColor: function( name ){
				var props    = 'borderTopColor,borderRightColor,borderBottomColor,borderLeftColor'.split( ',' ),
					top      = this.get( props[ 0 ] ),
					right    = this.get( props[ 1 ] ),
					bottom   = this.get( props[ 2 ] ),
					left     = this.get( props[ 3 ] ),
					ret      = new FrexibleProperty( name, top, right, bottom, left ),
					all, _0, _1, getColor;
				if( ret.isValid() === true ) return ret;
				ret.kill();
				getColor = this.getColor;
				all = this.style[ name ].split( ' ' );
				_0  = all[ 0 ];
				_1  = all[ 1 ];
				switch( all.length ){
					case 1 :
						top    = getColor( _0, props[ 0 ] );
						right  = getColor( _0, props[ 1 ] );
						bottom = getColor( _0, props[ 2 ] );
						left   = getColor( _0, props[ 3 ] );
						break;
					case 2 :
						top    = getColor( _0, props[ 0 ] );
						right  = getColor( _1, props[ 1 ] );
						bottom = getColor( _0, props[ 2 ] );
						left   = getColor( _1, props[ 3 ] );
						break;
					case 3 :
						top    = getColor( _0,       props[ 0 ] );
						right  = getColor( _1,       props[ 1 ] );
						bottom = getColor( all[ 2 ], props[ 2 ] );
						left   = getColor( _1,       props[ 3 ] );
						break;
					case 4 :
						top    = getColor( _0,       props[ 0 ] );
						right  = getColor( _1,       props[ 1 ] );
						bottom = getColor( all[ 2 ], props[ 2 ] );
						left   = getColor( all[ 3 ], props[ 3 ] );
						break;
				};
				return new FrexibleProperty( name, top, right, bottom, left );
			}
		}
	);
	function camelizeHash( obj ){
		var p, _p, came = Util.camelize;
		for( p in obj ){
			_p = came( p );
			if( _p === p ) continue;
			obj[ _p ] = obj[ _p ] || obj[ p ];
			delete obj[ p ];
		};
	};	
	return {
		create: function( css ){
			return new WrappedStyle( camelizeHash( p ) );
		}
	};
})();

var XDocument = ( function( window, document ){
	
	var getIndex  = Util.getIndex;
	var ROOT_LIST = [];
	var DEF_ATTRS = {};
	var AUTO      = Number.POSITIVE_INFINITY;
	var FULL      = DEF_ATTRS; // something unigue value;
	var FLOOR     = Math.floor;
	
	DEF_ATTRS.LENGTH            =  1;
	DEF_ATTRS.PERCENT           =  2;
	DEF_ATTRS.COLOR             =  4;
	DEF_ATTRS.U_DECIMAL         =  8;
	DEF_ATTRS.NUMERICAL         = 16;
	DEF_ATTRS.BOOLEAN           = 32;
	DEF_ATTRS.QUARTET           = 64;
	DEF_ATTRS.URL               = 128;
	DEF_ATTRS.FONT_NAME         = 256;
	DEF_ATTRS.LIST              = 512;
	DEF_ATTRS.AUTO              = 1024;
	DEF_ATTRS.COMBI             = 2048;
	DEF_ATTRS.BORDER_STYLE      = 'none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset'.split(',');
	DEF_ATTRS.POSITION_X        = 'left,center,right'.split(',');
	DEF_ATTRS.POSITION_Y        = 'top,center,bottom'.split(',');
	DEF_ATTRS.ALIGN             = 'left,center,right,justify'.split(',');
	DEF_ATTRS.TEXT_DECORATION   = 'none,underline,overline,line-through,blink'.split(',');
	DEF_ATTRS.TEXT_TRANSFORM    = 'none,capitalize,lowercase,uppercase'.split(',');
	DEF_ATTRS.WIDTH_HEIGHT      = 'auto'.split(',');
	DEF_ATTRS.BOX_SIZING        = 'content-box,padding-box,border-box,margin-box'.split(',');
	DEF_ATTRS.PAINT             = 1; // 再描画のみ必要
	DEF_ATTRS.REFLOW            = 2; // レイアウトの再計算が必要
	DEF_ATTRS.FONT              = 3; // フォントサイズが変更された
	DEF_ATTRS.CONTENT_UPDATE    = 4; // コンテンツが変更された
	
	DEF_ATTRS.borderWidth    = [ DEF_ATTRS.REFLOW,  0, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH      ]; // em [ top, right, bottom, left ]
	DEF_ATTRS.borderColor    = [ DEF_ATTRS.PAINT,   4, DEF_ATTRS.QUARTET | DEF_ATTRS.DEF_COLOR   ]; // color [ top, right, bottom, left ]
	DEF_ATTRS.borderStyle    = [ DEF_ATTRS.PAINT,   8, DEF_ATTRS.QUARTET | DEF_ATTRS.LIST, DEF_ATTRS.BORDER_STYLE ]; // string [ top, right, bottom, left ]
	DEF_ATTRS.cornerRadius   = [ DEF_ATTRS.PAINT,  12, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ]; // em, px [ top, right, bottom, left ]
	DEF_ATTRS.bgColor        = [ DEF_ATTRS.PAINT,  16, DEF_ATTRS.COLOR     ]; // color
	DEF_ATTRS.bgAlpha        = [ DEF_ATTRS.PAINT,  17, DEF_ATTRS.U_DECIMAL ]; // 0 - 1
	DEF_ATTRS.bgImgUrl       = [ DEF_ATTRS.PAINT,  18, DEF_ATTRS.URL       ]; // url
	DEF_ATTRS.bgImgRepeatX   = [ DEF_ATTRS.PAINT,  19, DEF_ATTRS.BOOLEAN   ]; // true / false
	DEF_ATTRS.bgImgRepeatY   = [ DEF_ATTRS.PAINT,  20, DEF_ATTRS.BOOLEAN   ]; // true / false
	DEF_ATTRS.bgImgPositionX = [ DEF_ATTRS.PAINT,  21, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT | DEF_ATTRS.LIST, DEF_ATTRS.POSITION_X ]; // em %, px, string
	DEF_ATTRS.bgImgPositionY = [ DEF_ATTRS.PAINT,  22, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT | DEF_ATTRS.LIST, DEF_ATTRS.POSITION_Y ]; // em %, px, string
	DEF_ATTRS.shadowColor    = [ DEF_ATTRS.PAINT,  23, DEF_ATTRS.COLOR     ]; // color
	DEF_ATTRS.shadowAlpha    = [ DEF_ATTRS.PAINT,  24, DEF_ATTRS.U_DECIMAL ]; // 0 - 1
	DEF_ATTRS.shadowOffsetX  = [ DEF_ATTRS.PAINT,  25, DEF_ATTRS.LENGTH    ]; // em
	DEF_ATTRS.shadowOffsetY  = [ DEF_ATTRS.PAINT,  26, DEF_ATTRS.LENGTH    ]; // em
	DEF_ATTRS.shadowBlur     = [ DEF_ATTRS.PAINT,  27, DEF_ATTRS.LENGTH    ]; // em
	DEF_ATTRS.shadowSpread   = [ DEF_ATTRS.PAINT,  28, DEF_ATTRS.LENGTH    ]; // em
	DEF_ATTRS.shadowInset    = [ DEF_ATTRS.PAINT,  29, DEF_ATTRS.BOOLEAN   ]; // true / false
	
	DEF_ATTRS.color          = [ DEF_ATTRS.PAINT,  30, DEF_ATTRS.COLOR     ]; // color
	DEF_ATTRS.fontFamily     = [ DEF_ATTRS.FONT,   31, DEF_ATTRS.FONT_NAME ]; // string
	DEF_ATTRS.fontSize       = [ DEF_ATTRS.FONT,   32, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ]; // em, %
	DEF_ATTRS.bold           = [ DEF_ATTRS.FONT,   33, DEF_ATTRS.BOOLEAN   ]; // true / false
	DEF_ATTRS.italic         = [ DEF_ATTRS.FONT,   34, DEF_ATTRS.BOOLEAN   ]; // true / false
	DEF_ATTRS.lineHeight     = [ DEF_ATTRS.FONT,   35, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT | DEF_ATTRS.NUMERICAL ]; // em, %, 
	DEF_ATTRS.letterSpacing  = [ DEF_ATTRS.FONT,   36, DEF_ATTRS.LENGTH    ]; // em
	DEF_ATTRS.wordSpacing    = [ DEF_ATTRS.FONT,   37, DEF_ATTRS.LENGTH    ];
	DEF_ATTRS.align          = [ DEF_ATTRS.FONT,   38, DEF_ATTRS.LIST, DEF_ATTRS.ALIGN           ];
	DEF_ATTRS.decoration     = [ DEF_ATTRS.PAINT,  39, DEF_ATTRS.LIST, DEF_ATTRS.TEXT_DECORATION ];
	DEF_ATTRS.transform      = [ DEF_ATTRS.FONT,   40, DEF_ATTRS.LIST, DEF_ATTRS.TEXT_TRANSFORM  ];
	DEF_ATTRS.textShadowColor   = [ DEF_ATTRS.PAINT,  41, DEF_ATTRS.COLOR     ];
	DEF_ATTRS.textShadowOffsetX = [ DEF_ATTRS.PAINT,  42, DEF_ATTRS.LENGTH    ];
	DEF_ATTRS.textShadowOffsetY = [ DEF_ATTRS.PAINT,  43, DEF_ATTRS.LENGTH    ];
	DEF_ATTRS.shadowBlur     = [ DEF_ATTRS.PAINT,  44, DEF_ATTRS.LENGTH    ];
	
	DEF_ATTRS.width              = [ DEF_ATTRS.REFLOW, 45, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT, DEF_ATTRS.WIDTH_HEIGHT ];
	DEF_ATTRS.minWidth           = [ DEF_ATTRS.REFLOW, 46, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
	DEF_ATTRS.maxWidth           = [ DEF_ATTRS.REFLOW, 47, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
	DEF_ATTRS.height             = [ DEF_ATTRS.REFLOW, 48, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT, DEF_ATTRS.WIDTH_HEIGHT ];
	DEF_ATTRS.minHeight          = [ DEF_ATTRS.REFLOW, 49, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
	DEF_ATTRS.maxHeight          = [ DEF_ATTRS.REFLOW, 50, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
	DEF_ATTRS.padding            = [ DEF_ATTRS.REFLOW, 51, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
	DEF_ATTRS.margin             = [ DEF_ATTRS.REFLOW, 55, DEF_ATTRS.QUARTET | DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
	DEF_ATTRS.sizing             = [ DEF_ATTRS.REFLOW, 59, DEF_ATTRS.LIST, DEF_ATTRS.BOX_SIZING ];
	DEF_ATTRS.pageBox            = [ DEF_ATTRS.REFLOW, 60, DEF_ATTRS.BOOLEAN   ]; // true / false
	DEF_ATTRS.x = DEF_ATTRS.left = [ DEF_ATTRS.REFLOW, 61, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
	DEF_ATTRS.y = DEF_ATTRS.top  = [ DEF_ATTRS.REFLOW, 62, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
	DEF_ATTRS.bottom             = [ DEF_ATTRS.REFLOW, 63, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
	DEF_ATTRS.right              = [ DEF_ATTRS.REFLOW, 64, DEF_ATTRS.LENGTH | DEF_ATTRS.PERCENT ];
	
	var ATTRS = ( function(){
		var ret = {},
			obj = DEF_ATTRS,
			p;
		for( p in obj ){
			if( Type.isArray( obj[ p ] ) === true ){
				ret[ p ] = obj[ p ][ 1 ];
			};
		};
		return ret;
	})();
	
	/**
	 * 再計算と再描画
	 * redraw 再描画はパラメータ変更後に setTimeout で
	 * reflow 再計算は値が get された場合 invalidate が サイズだったら
	 * または再描画前に invalidate がサイズなフラグが足っていたら 
	 */
	
	var BasicLayoutManager = Class.create(
		'BasicLayoutManager',
		Class.POOL_OBJECT,
		{
			Constructor : function(){
				
			},
			redraw : function( nodeData ){
				var root = nodeData.__root;
				root.dirty === DEF_ATTRS.REFLOW && this.reflow( root );
				
				// draw
			},
			reflow : function( nodeData, allowW, allowH ){
				nodeData.preMesure( allowW, allowH );
				
				var children = nodeData.children,				
					contentW = nodeData.contentWidth,
					contentH = nodeData.contentHeight,
					autoW    = contentW === AUTO,
					autoH    = contentH === AUTO,
					auto, calc, childW, childH, child, i, style, data,
					t, r, b, l;			
				if( children ){
					auto     = autoW && autoH;
					childW   = 0;
					childH   = 0;
					calc     = BasicLayoutManager.calcValue;			
					for( i = children.length; i; ){
						child = children[ --i ];
						style = child.__style;
						if( style ){
							data = style.data;
							t = calc( data[ ATTRS.top ],    contentH );
							r = calc( data[ ATTRS.right ],  contentW );
							b = calc( data[ ATTRS.bottom ], contentH );
							l = calc( data[ ATTRS.left ],   contentW );
						} else {
							t = r = b = l = 0;
						};
						if( child instanceof LayoutBoxPrivate ){
							child.layoutManager.reflow( child, contentW - r - l, contentH - t - b );
						} else {
							child.preMesure( contentW - r - l, contentH - t - b );
							child.mesure();
							child.postMesure();
						};
						if( !auto ) continue;
						if( autoW && childW < child.boxWidth  + r + l ) childW = child.boxWidth  + r + l;
						if( autoH && childH < child.boxHeight + t + b ) childH = child.boxHeight + t + b;						
					};
					if( autoW )	nodeData.contentWidth  = childW;
					if( autoH ) nodeData.contentHeight = childH;
				};
				( autoW || autoH ) && nodeData.postMesure();
				
				delete nodeData.dirty;
			}
		}
	);
	BasicLayoutManager.finalValue = function( styleValue, styleMin, styleMax, srcValue ){
		var calc = BasicLayoutManager.calcValue,
			v    = calc( styleValue, srcValue ),
			min  = calc( styleMin,   srcValue ),
			max  = calc( styleMax,   srcValue );
		if( v < min ) return min;
		if( max < v ) return max;
		return v;
	};
	BasicLayoutManager.calcValue = function( styleValue, srcValue ){
		switch( styleValue ){
			case 0 :
				return 0;
			case AUTO :
				return AUTO;
			case FULL :
				return srcValue; // 100%
			default :
				if( 1 <= styleValue ) return styleValue; // legth
				if( -1 < styleValue ) return FLOOR( srcValue * styleValue ); // %
		};
		return styleValue; // - length
	};
	BasicLayoutManager.advancedCalcValue = function( styleValue, srcValue ){
		switch( styleValue ){
			case 0 :
				return 0;
			case AUTO :
				return srcValue;
			case FULL :
				throw new Error( 'advancedCalcValue FULL' ); 
				// return ; // 100%
			default :
				if( 1 <= styleValue ) return styleValue; 
				if( -1 < styleValue ) return FLOOR( ( srcValue / ( 1 - styleValue ) ) * styleValue ); // %
		};
		return styleValue; // - length
	};
	
	var NodeStylePrivate = Class.create(
		Class.PRIVATE_DATA | Class.POOL_OBJECT,
		{
			fontCssText   : null,
			colorCssText  : null,
			layoutCssText : null,
			Constructor : function(){
				this.data  = [];
				this.dirty = 0;
			},
			register : function( node ){
				var root  = node.__root,
					roots = this.rootList,
					nodes = this.nodeList;
				if( !roots ){
					this.rootList = [ root ];
				} else
				if( getIndex( roots, root ) === -1 ) roots[ roots.length ] = root;
				
				if( !nodes ){
					this.nodeList = [ node ];
					return;
				};
				if( getIndex( nodes, node ) === -1 ) nodes[ nodes.length ] = node;
			},
			unRegister : function( node ){
				var nodes = this.nodeList,
					i     = getIndex( nodes, node ),
					root  = node._root,
					roots = this.rootList,
					j     = getIndex( roots, root );
				if( i !== -1 && nodes.splice( i, 1 ) && nodes.length === 0 ) delete this.nodeList;
				if( j !== -1 && roots.splice( j, 1 ) && roots.length === 0 ) delete this.rootList;
			},
			clone : function(){
				var styleClass = Class.getClass( this.User ),
					dataClass  = Class.getClass( this );
			},
			/*
			 * opt_unit は getter のみ
			 */
			attr : function( prop, v, opt_unit ){
				var update    = prop[ 0 ],
					propID    = prop[ 1 ],
					type      = prop[ 2 ],
					list      = prop[ 3 ],
					length    = !!( type & DEF_ATTRS.LENGTH    ),
					percent   = !!( type & DEF_ATTRS.PERCENT   ),
					color     = !!( type & DEF_ATTRS.COLOR     ),
					uDecimal  = !!( type & DEF_ATTRS.U_DECIMAL ),
					numerical = !!( type & DEF_ATTRS.NUMERICAL ),
					flag      = !!( type & DEF_ATTRS.BOOLEAN   ),
					quartet   = !!( type & DEF_ATTRS.QUARTET   ),
					url       = !!( type & DEF_ATTRS.URL       ),
					fontName  = !!( type & DEF_ATTRS.FONT_NAME ),
					//list      = !!( type & DEF_ATTRS.LIST      ),
					combi     = !!( type & DEF_ATTRS.COMBI     ),
					data      = this.data,
					_v        = -1,
					i, l, nodes, root;
				/*
				 * Setter
				 */
				if( v !== undefined ){
					if( Type.isNumber( v ) === true ){
						if( numerical === false ){
							if( uDecimal === false || v < 0 || 1 < v ) throw new Error( '' );
						};
					} else
					if( Type.isBoolean( v ) === true ){
						if( flag === false ) throw new Error( '' );
					} else
					if( Type.isString( v ) === true ){
						if( url === false && fontName === false ){
							if( v.indexOf( ' ' ) !== -1 ){
								v = v.split( ' ' );
							} else {
								if( length === false && percent === false && color === false ) throw new Error( '' );
							};
						};
					};					
					if( Type.isArray( v ) === true ){
						if( v.length <= 4 && quartet === true ){
							type ^= DEF_ATTRS.QUARTET;
						} else
						if( v.length === 2 && combi === true ){
							type ^= DEF_ATTRS.COMBI;
						} else {
							throw new Error( '' );
						};
						switch( v.length ){
							case 1 :
								this.attr( [ propID  , type, list ], v[ 0 ] );
								this.attr( [ ++propID, type, list ], v[ 0 ] );
								this.attr( [ ++propID, type, list ], v[ 0 ] );
								this.attr( [ ++propID, type, list ], v[ 0 ] );
								break;
							case 2 :
								this.attr( [ propID  , type, list ], v[ 0 ] );
								this.attr( [ ++propID, type, list ], v[ 1 ] );
								this.attr( [ ++propID, type, list ], v[ 0 ] );
								this.attr( [ ++propID, type, list ], v[ 1 ] );
								break;
							case 3 :
								this.attr( [ propID  , type, list ], v[ 0 ] );
								this.attr( [ ++propID, type, list ], v[ 1 ] );
								this.attr( [ ++propID, type, list ], v[ 2 ] );
								this.attr( [ ++propID, type, list ], v[ 1 ] );
								break;
							case 4 :
								this.attr( [ propID  , type, list ], v[ 0 ] );
								this.attr( [ ++propID, type, list ], v[ 1 ] );
								this.attr( [ ++propID, type, list ], v[ 2 ] );
								this.attr( [ ++propID, type, list ], v[ 3 ] );
								break;
							default :
						};
						return this.User;
					};
					switch( update ){
						case DEF_ATTRS.REFLOW :
							delete this.layoutCssText;
							break;
						case DEF_ATTRS.PAINT :
							delete this.colorCssText;
							break;
						case DEF_ATTRS.FONT :
							delete this.fontCssText;
					};

					if( this.dirty < update ){
						this.dirty = update;
						roots = this.rootList;
						for( i = 0, l = roots.length; i < l; ++i ){
							root = roots[ i ];
							if( root.dirty < update ) root.dirty = update;
						};
					};
					
					if( list ) _v = Util.getIndex( list, v );
					data[ propID ] = _v !== -1 ? _v : v;
					
					switch( prop ){
						case DEF_ATTRS.left  :
						case DEF_ATTRS.right :
							this.ltrtWidth = data[ DEF_ATTRS.left[ 0 ] ] === undefined && data[ DEF_ATTRS.right[ 0 ] ] === undefined;
							break;
						case DEF_ATTRS.top    :
						case DEF_ATTRS.bottom :
							this.tpbtHeight = data[ DEF_ATTRS.top[ 0 ] ] === undefined && data[ DEF_ATTRS.bottom[ 0 ] ] === undefined;
							break;
						case DEF_ATTRS.width :
							this.autoWidth = v === AUTO;
							this.prctWidth = v === FULL || v < 1;
							break;
						case DEF_ATTRS.height :
							this.autoHeight = v === AUTO;
							this.prctHeight   = v === FULL || v < 1;
							break;
					};					
					return this.User;
				};
				v = data[ propID ];
				// Unit
				if( quartet === true ) return [ v, data[ ++propID ], data[ ++propID ], data[ ++propID ] ];
				if( combi === true ) return [ v, data[ ++propID ] ];
				if( list && Type.isNumber( v ) === true ) return list[ v ];
				return v;
			},
			cssText : function(){
				if( this.fontCssText   === null ) this.fontCssText   = this.createFontCssText();
				if( this.layoutCssText === null ) this.layoutCssText = this.createLayoutCssText();
				if( this.colorCssText  === null ) this.colorCssText  = this.createColorCssText();
				return [ this.fontCssText, this.colorCssText, this.layoutCssText ].join( ';' );
			},
			createFontCssText : function(){
				var data = this.data,
					css  = [],
					v;
				if( v = data[ ATTRS.fontFamily    ] ) css[ 0 ] = 'font-family:' + v;
				if( v = data[ ATTRS.fontSize      ] ) css[ css.length - 1 ] = 'font-size:' + v;
				if( v = data[ ATTRS.bold          ] ) css[ css.length - 1 ] = 'font-weight:bold';
				if( v = data[ ATTRS.bold          ] ) css[ css.length - 1 ] = 'font-style:italic';
				if( v = data[ ATTRS.lineHeight    ] ) css[ css.length - 1 ] = 'line-height:' + v;
				if( v = data[ ATTRS.letterSpacing ] ) css[ css.length - 1 ] = 'letter-spacing:' + v;
				if( v = data[ ATTRS.wordSpacing   ] ) css[ css.length - 1 ] = 'word-spacing:' + v;
				if( v = data[ ATTRS.align         ] ) css[ css.length - 1 ] = 'text-align:' + DEF_ATTRS.ALIGN[ v ];
				if( v = data[ ATTRS.transform     ] ) css[ css.length - 1 ] = 'text-transform:' + DEF_ATTRS.TEXT_TRANSFORM[ v ];
				return css.join( ',' );
			},
			createColorCssText : function(){
				var data = this.data,
					css  = [],
					v, x, y, c, b;
				if( v = data[ ATTRS.borderColor ]      ) css[ 0 ] = 'border-color:' + v;
				if( v = data[ ATTRS.borderStyle + 0 ]  ) css[ css.length - 1 ] = 'border-top-style:' + DEF_ATTRS.BORDER_STYLE[ v ];
				if( v = data[ ATTRS.borderStyle + 1 ]  ) css[ css.length - 1 ] = 'border-right-style:' + DEF_ATTRS.BORDER_STYLE[ v ];
				if( v = data[ ATTRS.borderStyle + 2 ]  ) css[ css.length - 1 ] = 'border-bottom-style:' + DEF_ATTRS.BORDER_STYLE[ v ];
				if( v = data[ ATTRS.borderStyle + 3 ]  ) css[ css.length - 1 ] = 'border-left-style:' + DEF_ATTRS.BORDER_STYLE[ v ];
				if( v = data[ ATTRS.cornerRadius + 0 ] ) css[ css.length - 1 ] = 'corner-radius-top:' + v;
				if( v = data[ ATTRS.cornerRadius + 1 ] ) css[ css.length - 1 ] = 'corner-radius-right:' + v;
				if( v = data[ ATTRS.cornerRadius + 2 ] ) css[ css.length - 1 ] = 'border-radius-bottom:' + v;
				if( v = data[ ATTRS.cornerRadius + 3 ] ) css[ css.length - 1 ] = 'border-radius-left:' + v;
				if( v = data[ ATTRS.bgColor          ] ) css[ css.length - 1 ] = 'background-color:' + v;
				// ATTRS.bgAlpha
				if( v = data[ ATTRS.bgImgUrl         ] ) css[ css.length - 1 ] = 'background-image:url(' + v + ')';
				x = data[ ATTRS.bgImgRepeatX ];
				y = data[ ATTRS.bgImgRepeatY ];
				if( x && y ){
					css[ css.length - 1 ] = 'background-repeat:repeat';
				} else
				if( x ){
					css[ css.length - 1 ] = 'background-repeat:repeat-x';
				} else 
				if( y ){
					css[ css.length - 1 ] = 'background-repeat:repeat-y';
				};
				x = data[ ATTRS.bgImgPositionX ];
				y = data[ ATTRS.bgImgPositionY ];
				if( x && y ){
					css[ css.length - 1 ] = 'background-position:' + x + ' ' + y;
				} else
				if( x ){
					css[ css.length - 1 ] = 'background-position:' + x + ' 0';
				} else 
				if( y ){
					css[ css.length - 1 ] = 'background-position:0 ' + y;
				};
				if( v = data[ ATTRS.color ]      ) css[ css.length - 1 ] = 'color:' + v;
				if( v = data[ ATTRS.decoration ] ) css[ css.length - 1 ] = 'text-decoration:' + DEF_ATTRS.TEXT_DECORATION[ v ];
				x = data[ ATTRS.textShadowOffsetX ];
				y = data[ ATTRS.textShadowOffsetY ];
				b = data[ ATTRS.textShadowBlur ];
				c = data[ ATTRS.textShadowColor ];
				if( c || x || y || b ){
					css[ css.length - 1 ] = 'text-shadow:' + x + ' ' + y + ' ' + b + ' ' + c;
				};
				/*
	ATTRS.shadowColor    = [ DEF_ATTRS.PAINT,  23, DEF_ATTRS.COLOR     ]; // color
	ATTRS.shadowAlpha    = [ DEF_ATTRS.PAINT,  24, DEF_ATTRS.U_DECIMAL ]; // 0 - 1
	ATTRS.shadowOffsetX  = [ DEF_ATTRS.PAINT,  25, DEF_ATTRS.LENGTH    ]; // em
	ATTRS.shadowOffsetY  = [ DEF_ATTRS.PAINT,  26, DEF_ATTRS.LENGTH    ]; // em
	ATTRS.shadowBlur     = [ DEF_ATTRS.PAINT,  27, DEF_ATTRS.LENGTH    ]; // em
	ATTRS.shadowSpread   = [ DEF_ATTRS.PAINT,  28, DEF_ATTRS.LENGTH    ]; // em
	ATTRS.shadowInset    = [ DEF_ATTRS.PAINT,  29, DEF_ATTRS.BOOLEAN   ]; // true / false
				*/
			},
			createBoxShadowCssText : function(){
				
			},
			createBGAlphaCssText : function(){
				
			},
			createTextShadowCssText : function(){
				
			},
			createLayoutCssText : function(){
				
			}
		}
	);
	
	var NodeStyle = Class.create(
		'NodeStyle',
		Class.POOL_OBJECT,
		NodeStylePrivate,
		{
			Constructor : function(){
				NodeStyle.newPrivateData( this );
			},
			borderWidth : function( v ){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.borderWidth, v );
			},
			borderColor : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.borderColor, v );
			},
			borderStyle : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.borderStyle, v );
			},
			cornerRadius : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.cornerRadius, v );
			},
			bgColor : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgColor, v );
			},
			bgAlpha : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgAlpha, v );
			},
			bgImgUrl : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgUrl, v );
			},
			bgImgRepeatX : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgRepeatX, v );
			},
			bgImgRepeatY : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgRepeatY, v );
			},
			bgImgPositionX : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgPositionX, v );
			},
			bgImgPositionY : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.bgImgPositionY, v );
			},
			shadowColor : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowColor, v );
			},
			shadowAlpha : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowAlpha, v );
			},
			shadowOffsetX : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowOffsetX, v );
			},
			shadowOffsetY : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowOffsetY, v );
			},
			shadowBlur : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowBlur, v );
			},
			shadowSpread : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowSpread, v );
			},
			shadowInset : function(){
				return NodeStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowInset, v );
			},
			color : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.color, v );
			},
			fontFamily : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.fontFamily, v );
			},
			fontSize : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.fontSize, v );
			},
			bold : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.bold, v );
			},
			italic : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.italic, v );
			},
			lineHeight : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.lineHeight, v );
			},
			letterSpacing : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.letterSpacing, v );
			},
			wordSpacing : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.wordSpacing, v );
			},
			align : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.align, v );
			},
			decoration : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.decoration, v );
			},
			transform : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.transform, v );
			},
			textShadowColor : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.textShadowColor, v );
			},
			textShadowOffsetX : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.textShadowOffsetX, v );
			},
			textShadowOffsetY : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.textShadowOffsetY, v );
			},
			shadowBlur : function( v ){
				return TypoStyle.getPrivateData( this ).attr( DEF_ATTRS.shadowBlur, v );
			},
			cssText : function(){
				return TypoStyle.getPrivateData( this ).cssText();
			}
		}
	);

	var NodePrivate = Class.create(
		'NodePrivate',
		Class.PRIVATE_DATA | Class.POOL_OBJECT,
		{
			elmWrap           : null,
			elmExtend         : null,
			textNode          : null,
			boxX              : 0,
			boxY              : 0,
			boxWidth          : 0,
			boxHeight         : 0,
			contentL          : 0,
			contentT          : 0,
			contentR          : 0,
			contentB          : 0,
			borderL           : 0,
			borderT           : 0,
			borderR           : 0,
			borderB           : 0,
			paddingL          : 0,
			paddingT          : 0,
			paddingR          : 0,
			paddingB          : 0,
			marginL           : 0,
			marginT           : 0,
			marginR           : 0,
			marginB           : 0,
			boxSizingOffsetLR : 0,
			boxSizingOffsetTB : 0,		
			contentWidth      : 0,
			minContentWidth   : 0,
			maxContentWidth   : AUTO,
			contentHeight     : 0,
			minContentHeight  : 0,
			maxContentHeight  : AUTO,
			Constructor   : function( __root, __parent ){
				this.__root   = __root;
				if( __parent ) this.__parent = __parent;
			},
			style : function( v ){
				if( v instanceof NodeStyle ){
					if( v !== this._style ){
						this.__style && this.__style.unRegister( this );
						this._style = v;
						this.__style = StylePrivate.getPrivateData( v );					
						this.__style.register( this );						
					};
					return this.User;
				} else
				if( v === null ){
					this.__style && this.__style.unRegister( this );
					delete this._style;
					delete this.__style;
					return this.User;
				};
				return this._style;
			},
			content : function( v ){
				if( Type.isString( v ) === true ){
					if( !this.textNode || ( this.textNode && this.textNode.data !== v ) ){
						this._content = v;
						this.updateContent = true;
					};
					return this.User;
				} else
				if( v === null ){
					if( this._content !== v && this.textNode ){
						this._content = v;
						this.updateContent = true;
					};
					return this.User;
				};
				if( this._content ) return this._content;
				if( this._content === null ) return null;
				if( this.textNode ) return this.textNode.data;
				return null;
			},
			/**
			 * 要素の追加・削除
			 * 1. ペイントがある // 予約のみ
			 * 2. コンテンツがある // 予約のみ *
			 * 3. コンテンツを削除 // 予約のみ
			 * 4. 要素を削除 // 予約のみ
			 * 
			 * コンテンツの再計算
			 * 0. 要素追加して css セット
			 * 1. コンテンツの変更
			 * 2. font 指定の変更
			 * 3. contentWidth の変更 （コンテンツの高さの再計算） 前回の contentWidth の保持
			 * 
			 * contentSize, scrollSize の決定
			 */
			musure : function( dirty ){
				var content = this._content,
					root    = this.__root,
					style   = this.__style,
					w       = this.contentWidth,
					h       = this.contentHeight;
				switch( this.updateContent === true ? DEF_ATTRS.CONTENT_UPDATE : dirty ){
					case DEF_ATTRS.CONTENT_UPDATE : // コンテンツが変更された
						this.paint( 0 );
						this.lastContentWidth = -1;
					case DEF_ATTRS.FONT   : // フォントサイズが変更された
					case DEF_ATTRS.REFLOW : // レイアウトの再計算が必要
						/* http://web-designs.seesaa.net/article/188400668.html
						 * min-width の値が max-width の値より大きい場合は、max-width の値は min-width の値に設定される。
						 * 
						 * テキストノードがあり
						 * 1. contentWidth === AUTO
						 *     style を更新して contentWidth の決定
						 *     min or max に引っかかったら style 更新
						 *     contentHeight === AUTO の場合
						 *     textHeight の決定
						 *     contentHeight !== AUTO の場合 scrollHeight のみ更新
						 * 2. contentHeight === AUTO かつ 
						 *     コンテンツの高さの再取得が必要( contentWidth が最終計測時の contentWidth と一致 かつ フォント・コンテンツに変更無し の場合再取得不要)
						 *      style を更新して contentHeight の決定
						 *     必要でない
						 * 3. content のサイズがすでに決定している
						 *     コンテンツの高さの再取得が必要
						 *     必要でない
						 */   
						if( this.textNode ){
							if( w === AUTO ){
								this.commitStyle();
								w = this.contentWidth = this.textNode.offsetWidth;
								this.scrollWidth = w + this.contentL + this.contentR;
								if( this.maxContentWidth < w - this.boxSizingOffsetLR ) this.contentWidth = this.maxContentWidth + this.boxSizingOffsetLR;
								if( w - this.boxSizingOffsetLR < this.minContentWidth ) this.contentWidth = this.minContentWidth + this.boxSizingOffsetLR;
								this.lastContentWidth = this.contentWidth;
								
								w !== this.contentWidth && this.commitStyle();
								
								if( h === AUTO ){
									h = this.conetntHeight = this.textNode.offsetHeight;
									this.scrollHeight = h + this.contentT + this.contentB;
									if( this.maxContentHeight < h - this.boxSizingOffsetTB ) this.contentHeight = this.maxContentHeight + this.boxSizingOffsetTB;
									if( h - this.boxSizingOffsetTB < this.minContentHeight ) this.contentHeight = this.minContentHeight + this.boxSizingOffsetTB;
								} else {
									this.scrollHeight = this.textNode.offsetHeight + this.contentT + this.contentB;
								};
							} else
							if( h === AUTO ){
								if( w !== this.lastContentWidth || dirty !== DEF_ATTRS.REFLOW ){
									this.commitStyle();
									this.lastContentWidth  = w;
									h = this.conetntHeight = this.textNode.offsetHeight;
									this.scrollWidth       = w + this.contentL + this.contentR;
									this.scrollHeight      = h + this.contentT + this.contentB;
									if( this.maxContentHeight < h - this.boxSizingOffsetTB ) this.contentHeight = this.maxContentHeight + this.boxSizingOffsetTB;
									if( h - this.boxSizingOffsetTB < this.minContentHeight ) this.contentHeight = this.minContentHeight + this.boxSizingOffsetTB;								
								} else {
									this.scrollWidth  = w + this.contentL + this.contentR;
									this.scrollHeight = h + this.contentT + this.contentB;
									root.paintReserve( this );
								};
							} else {
								if( dirty !== DEF_ATTRS.REFLOW ){
									this.commitStyle();
									this.scrollWidth  = this.textNode.offsetWidth  + this.contentL + this.contentR;
									this.scrollHeight = this.textNode.offsetHeight + this.contentT + this.contentB;
								} else {
									root.paintReserve( this );
									this.scrollWidth  = w + this.contentL + this.contentR;
									this.scrollHeight = h + this.contentT + this.contentB;
								};
							};					
						} else {
							if( w === AUTO ) this.contentWidth  = w = 0 < this.minContentWidth  ? this.minContentWidth  : 0;
							if( h === AUTO ) this.contentHeight = h = 0 < this.minContentHeight ? this.minContentHeight : 0;
							this.scrollWidth  = w + this.contentL + this.contentR;
							this.scrollHeight = h + this.contentT + this.contentB;
							root.paintReserve( this );					
						};
						break;			
					case DEF_ATTRS.PAINT : // 再描画のみ必要
						root.paintReserve( this );
						break;						
				};
			},
			paint : function( dirty ){
				var content = this._content,
					style   = this.__style;				
				if( this.updateContent === true || ( style && style.hasPaint === true ) ){
					if( !this.elmWrap ){
						this.elmWrap = DOM.createDiv();
						this.__parent.addDisplayElement( this );
					};
					dirty !== 0 && this.commitStyle();			
					if( this.updateContent === true ){
						if( content !== null ){
							if( !this.textNode ){
								this.textNode = DOM.cerateText();
								this.elmWrap.appendChild( this.textNode );
							};
							this.textNode.data = content;							
						} else
						if( this.textNode ){
							DOM.correct( this.textNode );
							delete this.textNode;
							delete this.contentWidth;
							delete this.conetntHeight;
							delete this.scrollWidth;							
							delete this.scrollHeight;
						};					
					};
				} else
				if( this.elmWrap && content === null && ( !style || style.hasPaint === false ) ){
					this.__parent.removeDisplayElement( this );
					DOM.correct( this.elmWrap );
					delete this.contentWidth;
					delete this.conetntHeight;
				};
			},
			commitStyle : function(){
				var css;
				if( this.elmWrap ){
					css = this.__style ? this.__style.cssText( this ) : '';
					if( this.contentWidth  !== AUTO ) css += 'width:'  + this.contentWidth  + 'px';
					if( this.contentHeight !== AUTO ) css += 'height:' + this.contentHeight + 'px';
					this.elmWrap.style.cssText = css;
				};
			},
			/*
			 * 親の サイズを元に自身のサイズを計算していく
			 */
			preMesure : function( allowW, allowH ){
				var style    = this.__style,
					styles, calc, box, min, max,
					contentW, contentH, allowSize, boxMinus,
					paddingT, paddingR, paddingB, paddingL,
					borderT, borderR, borderB, borderL,
					marginT, marginR, marginB, marginL;

				if( style ){
					styles   = style.data;
					calc     = BasicLayoutManager.calcValue;
					box      = styles[ ATTRS.sizing ];
					
					// Width
					// 自身が ltrtWidth の場合 親が AUTO ではない
					// 自身が ltrtWidth でない場合自身が  AUTO はなくかつ親 が AUTO の場合自身は % でない
					if( style.ltrtWidth ? allowW !== AUTO : !style.autoWidth && ( allowW !== AUTO || !style.prctWidth ) ){
						if( style.ltrtWidth ){
							contentW = allowW; // - calc( styles[ ATTRS.left ], allowW ) - calc( styles[ ATTRS.right ], allowW );
						} else {
							contentW = BasicLayoutManager.finalValue( styles[ ATTRS.width ], styles[ ATTRS.minWidth ], styles[ ATTRS.maxWidth ], allowW );					
						};
						paddingR = calc( styles[ ATTRS.padding + 1 ], allowW );
						paddingL = calc( styles[ ATTRS.padding + 3 ], allowW );
						borderR  = styles[ ATTRS.border + 1 ];
						borderL  = styles[ ATTRS.margin + 3 ];
						marginR  = calc( styles[ ATTRS.margin + 1 ], allowW );
						marginL  = calc( styles[ ATTRS.margin + 3 ], allowW );
						this.boxWidth = contentW;
						boxMinus = 0;
						switch( box ){
							case 3 : // margin-box
								 boxMinus = - marginR - marginL;
							case 2 : // border-box
								 boxMinus -= borderR + borderL;
							case 1 : // padding-box
								 boxMinus -= paddingR + paddingL;
							// case 0 : // content-box
						};
						this.contentL     = marginL + borderL + paddingL;
						this.contentR     = marginR + borderR + paddingR;		
						this.contentWidth = contentW + boxMinus;
						this.boxSizingOffsetLR = boxMinus;
					} else {
						this.boxWidth = this.contentWidth = AUTO;
						min = styles[ ATTRS.minWidth ];
						max = styles[ ATTRS.maxWidth ];
						this.minContentWidth = 1 <= min ? min : 0;
						this.maxContentWidth = 1 <= max ? max : AUTO;
						delete this.boxSizingOffsetLR;
					};
					
					// Height
					if( style.tpbtHeight ? allowH !== AUTO : !style.autoHeight && ( allowH !== AUTO || !style.prctHeight ) ){												
						if( style.tpbtHeight ){
							contentH = allowH; // - calc( styles[ ATTRS.top ], allowH ) - calc( styles[ ATTRS.bottom ], allowH );
						} else {
							contentH = BasicLayoutManager.finalValue( styles[ ATTRS.height ], styles[ ATTRS.minHeight ], styles[ ATTRS.maxHeight ], allowH );
						};
						allowSize = styles[ ATTRS.pageBox ] === true ? allowH : allowW;
						paddingT  = calc( styles[ ATTRS.padding + 0 ], allowSize );// paddingTRBL の % 指定は 最大幅に対して TB でも幅に対して
						paddingB  = calc( styles[ ATTRS.padding + 2 ], allowSize );
						borderT   = styles[ ATTRS.border + 0 ];
						borderB   = styles[ ATTRS.border + 2 ];
						marginT   = calc( styles[ ATTRS.margin + 0 ], allowSize );// marginTRBL の % 指定は 最大幅に対して TB でも幅に対して
						marginB   = calc( styles[ ATTRS.margin + 2 ], allowSize );
						this.boxHeight = contentH;
						boxMinus = 0;
						switch( box ){
							case 3 : // margin-box
								 boxMinus = - marginT - marginR;
							case 2 : // border-box
								 boxMinus -= borderT + borderR;
							case 1 : // padding-box
								 boxMinus -= paddingT + paddingR;
							// case 0 : // content-box
						};			
						this.contentT      = marginT + borderT + paddingT;
						this.conetntB      = marginB + borderB + paddingB;			
						this.contentHeight = contentH + boxMinus;
						this.boxSizingOffsetTB = boxMinus;
					} else {
						this.boxHeight = this.contentHeight = AUTO;
						min = styles[ ATTRS.minHeight ];
						max = styles[ ATTRS.maxHeight ];
						this.minContentHeight = 1 <= min ? min : 0;
						this.maxContentHeight = 1 <= max ? max : AUTO;
						delete this.boxSizingOffsetTB;
					};
				} else {
					this.boxWidth  = this.contentWidth  = allowW;
					this.boxHeight = this.contentHeight = allowH;
					delete this.minContentHeight;
					delete this.maxContentHeight;
					delete this.contentL;
					delete this.contentT;
					delete this.contentR;
					delete this.contentB;
				};
			},
			/**
			 * 自身のコンテンツサイズを元に AUTO な width, height を確定していく
			 */
			postMesure : function(){
				var style    = this.__style,
					styles, calc, box,
					contentW, contentH, w, h
					contentSize, contentPlus;
				if( style ){
					styles   = style.data;
					calc     = BasicLayoutManager.advancedCalcValue;
					contentW = this.contentWidth;
					box      = styles[ ATTRS.sizing ];
					
					// Width
					if( this.boxWidth === AUTO ){
						paddingR = calc( styles[ ATTRS.padding + 1 ], contentW );					
						paddingL = calc( styles[ ATTRS.padding + 3 ], contentW );					
						borderR  = styles[ ATTRS.border + 1 ];					
						borderL  = styles[ ATTRS.border + 3 ];					
						marginR  = calc( styles[ ATTRS.margin + 1 ], contentW );
						marginL  = calc( styles[ ATTRS.margin + 3 ], contentW );
						contentPlus = 0;
						switch( box ){
							case 3 : // margin-box
								 contentPlus  = ( marginR + marginL );
							case 2 : // border-box
								 contentPlus += ( borderR + borderL );
							case 1 : // padding-box
								 contentPlus += ( paddingR + paddingL );
							// case 0 : // content-box
						};
						this.contentWidth = contentW;
						contentW += contentPlus;
						if( !style.ltrtWidth ){
							min = styles[ ATTRS.minWidth ];
							max = styles[ ATTRS.maxWidth ];
							if( contentW < min && 1 <= min && contentPlus < min ){
								this.contentWidth = min - contentPlus;
							} else
							if( max < contentW && 1 <= max && contentPlus < max ){
								this.contentWidth = max - contentPlus;
							};
						};
						this.contentL = marginL + borderL + paddingL;
						this.contentR = marginR + borderR + paddingR;
						this.boxWidth = this.contentWidth + this.contentL + this.contentR;
					};
					// Height
					if( this.boxHeight === AUTO ){
						contentH    = this.contentHeight;
						contentSize = styles[ ATTRS.pageBox ] === true ? contentH : contentW;
						paddingT    = calc( styles[ ATTRS.padding + 0 ], contentSize );// paddingTRBL の % 指定は 最大幅に対して TB でも幅に対して
						paddingB    = calc( styles[ ATTRS.padding + 2 ], contentSize );
						borderT     = styles[ ATTRS.border + 0 ];
						borderB     = styles[ ATTRS.border + 2 ];
						marginT     = calc( styles[ ATTRS.margin + 0 ], contentSize );// marginTRBL の % 指定は 最大幅に対して TB でも幅に対して
						marginB     = calc( styles[ ATTRS.margin + 2 ], contentSize );
						contentPlus = 0;
						switch( box ){
							case 3 : // margin-box
								 contentPlus  = ( marginT + marginB );
							case 2 : // border-box
								 contentPlus += ( borderT + borderB );
							case 1 : // padding-box
								 contentPlus += ( paddingT + paddingB );
							// case 0 : // content-box
						};
						this.contentHeight = contentH;
						contentH += contentPlus;
						if( !style.tpbtHeight ){
							min = styles[ ATTRS.minHeight ];
							max = styles[ ATTRS.maxHeight ];
							if( contentH < min && 1 <= min && contentPlus < min ){
								this.contentHeight = min - contentPlus;
							} else
							if( max < contentH && 1 <= max && contentPlus < max ){
								this.contentHeight = max - contentPlus;
							};
						};
						this.contentT  = marginT + borderT + paddingT;
						this.contentB  = marginB + borderB + paddingB;						
						this.boxHeight = this.contentHeight + this.contentT + this.contentB;
					};				
				} else {
					this.boxWidth  = this.contentWidth;
					this.boxHeight = this.contentHeight;
					delete this.minContentHeight;
					delete this.maxContentHeight;
					delete this.contentL;
					delete this.contentT;
					delete this.contentR;
					delete this.contentB;
				};
			},
			addDisplayElement : function( nodeData ){
				// 描画更新リストに追加
			},
			removeDisplayElement : function( nodeData ){
				// 描画更新リストに追加
				DOM.correct( nodeData.elmWrap );
				delete nodeData.elmWrap;
				delete nodeData.textNode;
				delete nodeData.contentWidth;
				delete nodeData.conetntHeight;
				delete nodeData.currentWidth;
				delete nodeData.currentHeight;			
			}
		}
	);
	var Node = Class.create(
		'Node',
		Class.POOL_OBJECT,
		NodePrivate,
		{
			Constructor : function( root, parent ){
				Node.newPrivateData( this,  LayoutBox.getPrivateData( root ), parent ? LayoutBox.getPrivateData( parent ) : undefined, this );
			},
			content : function( v ){
				return Node.getPrivateData( this ).content( v );
			},
			style : function( v ){
				return Node.getPrivateData( this ).paint( v );
			},
			remove : function(){
				Node.getPrivateData( this ).remove();
			},
			nodeIndex : function( v ){
				return Node.getPrivateData( this ).nodeIndex( v );
			},
			displayIndex : function(){
				
			},
			disabled : function( v ){
				return Node.getPrivateData( this ).disabled( v );
			},
			cursor : function( v ){
				return Node.getPrivateData( this ).cursor( v );
			},
			getX : function(){
				
			},
			getY : function(){
				
			},
			getWidth : function(){
				
			},
			getHeight : function(){
				
			},
			getAbsolutePositionX : function(){
				return Node.getPrivateData( this ).getAbsolutePositionX();
			},
			getAbsolutePositionY : function(){
				return Node.getPrivateData( this ).getAbsolutePositionY();
			},
			scrollTo : function( x, y ){
				Node.getPrivateData( this ).scrollTo( x, y );
			},
			scrollX : function( v ){
				return Node.getPrivateData( this ).scrollX( v );
			},
			scrollY : function( v ){
				return Node.getPrivateData( this ).scrollY( v );
			},
			addEventListener : function( type, handler, opt_thisObject ){
				Node.getPrivateData( this ).addEventListener( type, handler, opt_thisObject );
			},
			removeEventListener : function( type, handler ){
				Node.getPrivateData( this ).removeEventListener( type, handler );
			}
		}
	);
	
	var LayoutBoxPrivate = NodePrivate.inherits(
		'LayoutBoxPrivate',
		Class.POOL_OBJECT | Class.SUPER_ACCESS,
		{
			Constructor : function( layoutManager, _root, _parent ){
				this.layoutManager = layoutManager;
				this._root         = _root;
				this.paintList     = [];
				if( _parent ) this._parent = _parent;
			},
			mesure : function(){
				this.layoutManager.reflow( this );
			},
			paintReserve : function( nodeData ){
				var list = this.paintList;
				if( Util.getIndex( list, nodeData ) === -1 ) list[ list.length - 1 ] = nodeData;
			},
			paintRelease : function( nodeData ){
				var list = this.paintList,
					i    = Util.getIndex( list, nodeData );
				i === -1 && list.splice( i, 1 );
			},
			paint : function(){
				var list = this.paintList, i = list.length;
				for( ; i; ){
					list[ --i ].paint();
				};
			}
		}
	);
	
	var LayoutBox = Node.inherits(
		'LayoutBox',
		Class.POOL_OBJECT,
		LayoutBoxPrivate,
		{
			Constructor : function( layoutManager, root, parent ){
				LayoutBox.newPrivateData( this, layoutManager, LayoutBox.getPrivateData( root ), parent ? LayoutBox.getPrivateData( parent ) : undefined );
			},
			layoutManager : function( v ){
				
			},
			createLayoutBox : function(){
				
			},
			createContentBox : function(){
				
			}
		}
	);
	
	var RootNode = Node.inherits(
		'RootNode',
		Class.POOL_OBJECT,
		LayoutBoxPrivate,
		{
			Constructor : function(){
				RootNode.newPrivateData( this, BasicLayoutManager );
			}
		}
	);
	
})( window, document );