OSDN Git Service

Version 0.6.15, add X.Dom.BoxModel.
[pettanr/clientJs.git] / 0.6.x / js / dom / 15_XDomStyle.js
1
2
3 /*
4  * style 値の変更は、enterFrame 後にまとめて適用
5  * width(), height(), x(), y() 1em の取得時にも適用
6  * css3 の ie用 fix は X.UI レベルで行う
7  * 
8  * use X.Dom.Event
9  */
10 X.Dom.Style = {
11         
12         Type : {
13                 LENGTH            : 1,
14                 PERCENT           : 2,
15                 COLOR             : 2 < 2,
16                 U_DECIMAL         : 2 < 3,
17                 NUMERICAL         : 2 < 4,
18                 BOOLEAN           : 2 < 5,
19                 QUARTET           : 2 < 6,
20                 URL               : 2 < 7,
21                 FONT_NAME         : 2 < 8,
22                 TIME              : 2 < 9,
23                 CONTENT           : 2 < 10,
24                 LIST              : 2 < 11,
25                 AUTO              : 2 < 12,
26                 COMBI             : 2 < 13
27         },
28         
29         SPECIAL_VALUES : {
30                 AUTO : Number.POSITIVE_INFINITY,
31                 FULL : X.Dom // something unigue value; 100%
32         },
33         
34         PropNo : {},
35         
36         UNIT : {
37                 // '' : 0,
38                 'px'   : 0,
39                 'em'   : 1,
40                 'cm'   : 2,
41                 'mm'   : 3,
42                 'in'   : 4,
43                 '%'    : 5,
44                 'pct'  : 5,
45                 'ms'   : 6,
46                 's'    : 7,
47                 '#'    : 8,
48                 'rgb'  : 9,
49                 'rgba' : 10
50         },
51         
52         /* font-size -> fontSize */
53         _DICTIONARY_CAMELIZE : {},
54         
55         camelize : function( cssProp ){
56                 var me  = X.Dom.Style,
57                         parts, l, i, camelized;
58                 
59                 if( camelized = me._DICTIONARY_CAMELIZE[ cssProp ] ) return camelized;
60                 parts = cssProp.split( ' ' ).join( '' ).split( '-' );
61                 l     = parts.length;
62                 if( l === 1 ) return parts[ 0 ];
63                 
64                 camelized = cssProp.charAt(0) === '-'
65                   ? parts[ 0 ].charAt( 0 ).toUpperCase() + parts[ 0 ].substring( 1 )
66                   : parts[ 0 ];
67                 
68                 for( i = 1; i < l; ++i ){
69                         camelized += parts[ i ].charAt( 0 ).toUpperCase() + parts[ i ].substring( 1 );
70                 };
71                 return me._DICTIONARY_CAMELIZE[ cssProp ] = camelized;
72         },
73         
74         /* fontSize -> font-size */
75         /*
76         REG_LARGE : /[A-Z]/g,
77         uncamelize: function( str ){
78                 return str.split( ' ' ).join( '' ).replace( X.Dom.Style.REG_LARGE, '-$&' ).toLowerCase();
79         }, */
80         
81         CHAR_CODE_A : 'A'.charCodeAt( 0 ),
82         
83         _DICTIONARY_UNCAMELIZE : {},
84         
85         uncamelize : function( str ){
86                 var me  = X.Dom.Style,
87                         A   = me.CHAR_CODE_A,
88                         Z   = A + 25,
89                         uncamelized, l, chr, code;
90                 str = str.split( ' ' ).join( '' );
91                 if( uncamelized = me._DICTIONARY_UNCAMELIZE[ str ] ) return uncamelized;
92                 uncamelized = '';
93                 for( i = 0, l = str.length; i < l; ++i ){
94                         chr = str.charAt( i );
95                         code = chr.charCodeAt( 0 );
96                         uncamelized += ( A <= code && code <= Z ) ? '-' + chr : chr;
97                 };
98                 return me._DICTIONARY_UNCAMELIZE[ str ] = uncamelized.toLowerCase();
99         },
100         
101         objToCssText : function( obj ){
102                 var css           = [],
103                         me            = X.Dom.Style,
104                         uncamelize    = me.uncamelize,
105                         VENDER_PREFIX = me.VENDER_PREFIX,
106                         FIX_PROP      = me.SPECIAL_FIX_PROP,
107                         SPECIAL_FIX   = me.SPECIAL_FIX,
108                         p, name, sp;
109                 for( p in obj ){
110                         name = uncamelize( p );
111                         if( FIX_PROP[ name ] ){
112                                 sp = 1;
113                         } else {
114                                 css[ css.length ] = [ VENDER_PREFIX[ name ] || name, obj[ p ] ].join( ':' );
115                         };
116                 };
117                 sp && ( css[ css.length ] = SPECIAL_FIX( obj ) );
118                 return css.join( ';' );
119         },
120         
121         _UNIT_RATIO      : null,
122         _FONT_SIZE_RATIO : null,
123
124         //  https://developer.mozilla.org/en-US/docs/Web/CSS/transform
125         //  Firefox 3.5, ie9, Opera 10.5, Safari 3.1, Chrome
126         //  3D support Firefox 10, ie10, Safari 4.0, Chrome 12.0
127         // transform : void 0,
128         
129         //  https://developer.mozilla.org/ja/docs/Web/Guide/CSS/Using_CSS_transitions
130         //  Chrome 1.0, Firefox 4.0, ie10, Opera 10.5, Safari 3.2
131         //  Android 2.1, Firefox Android 4.0, Opera Mobile 10, Safari Mobile 3.2        
132         // transition : void 0
133         
134         // ブラウザ毎の getComputedStyle の戻り値 http://d.hatena.ne.jp/uupaa/20080928/1222543331
135
136         COLOR : {
137                 BLACK         : 0x0,
138                 RED           : 0xFF0000,
139                 LIME          : 0x00FF00,
140                 BLUE          : 0x0000FF,
141                 YELLOW        : 0xFFFF00,
142                 AQUA          : 0x00FFFF,
143                 CYAN          : 0x00FFFF,
144                 MAGENTA       : 0xFF00FF,
145                 FUCHSIA       : 0xFF00FF,
146                 WHITE         : 0xFFFFFF,
147                 GREEN         : 0x008000,
148                 PURPLE        : 0x800080,
149                 MAROON        : 0x800000,
150                 NAVY          : 0x000080,
151                 OLIVE         : 0x808000,
152                 TEAL          : 0x008080,
153                 GRAY          : 0x808080,
154                 SILVER        : 0xC0C0C0,
155                 DIMGRAY       : 0x696969,
156                 SLATEGRAY     : 0x708090,
157                 DARKGRAY      : 0xA9A9A9,
158                 GAINSBORO     : 0xDCDCDC,
159                 MIDNIGHTBLUE  : 0x191970,
160                 SLATEBLUE     : 0x6A5ACD,
161                 MEDIUMBLUE    : 0x0000CD,
162                 ROYALBLUE     : 0x4169E1,
163                 DODGERBLUE    : 0x1E90FF,
164                 SKYBLUE       : 0x87CEEB,
165                 STEELBLUE     : 0x4682B4,
166                 LIGHTBLUE     : 0xADD8E6,
167                 PALETURQUOISE : 0xAFEEEE,
168                 TURQUOISE     : 0x40E0D0,
169                 LIGHTCYAN     : 0xE0FFFF,
170                 AQUAMARINE    : 0x7FFFD4,
171                 DARKGREEN     : 0x006400,
172                 SEAGREEN      : 0x2E8B57,
173                 LIGHTGREEN    : 0x90EE90,
174                 CHARTREUSE    : 0x7FFF00,
175                 GREENYELLOW   : 0xADFF2F,
176                 LIMEGREEN     : 0x32CD32,
177                 YELLOWGREEN   : 0x9ACD32,
178                 OLIVEDRAB     : 0x6B8E23,
179                 DARKKHAKI     : 0xBCB76B,
180                 PALEGOLDENROD : 0xEEE8AA,
181                 LIGHTYELLOW   : 0xFFFFE0,
182                 GOLD          : 0xFFD700,
183                 GOLDENROD     : 0xDAA520,
184                 DARKGOLDENROD : 0xB8860B,
185                 ROSYBROWN     : 0xBC8F8F,
186                 INDIANRED     : 0xCD5C5C,
187                 SADDLEBROWN   : 0x8B4513,
188                 SIENNA        : 0xA0522D,
189                 PERU          : 0xCD853F,
190                 BURLYWOOD     : 0xDEB887,
191                 BEIGE         : 0xF5F5DC,
192                 WHEAT         : 0xF5DEB3,
193                 SANDYBROWN    : 0xF4A460,
194                 TAN           : 0xD2B48C,
195                 CHOCOLATE     : 0xD2691E,
196                 FIREBRICK     : 0xB22222,
197                 BROWN         : 0xA52A2A,
198                 SALMON        : 0xFA8072,
199                 ORANGE        : 0xFFA500,
200                 CORAL         : 0xFF7F50,
201                 TOMATO        : 0xFF6347,
202                 HOTPINK       : 0xFF69B4,
203                 PINK          : 0xFFC0CB,
204                 DEEPPINK      : 0xFF1493,
205                 PALEVIOLETRED : 0xDB7093,
206                 VIOLET        : 0xEE82EE,
207                 PLUM          : 0xDDA0DD,
208                 ORCHILD       : 0xDA70D6,
209                 DARKVIOLET    : 0x9400D3,
210                 BLUEVIOLET    : 0x8A2BE2,
211                 MEDIUMPURPLE  : 0x9370DB,
212                 THISTLE       : 0xD8BFD8,
213                 LAVENDER      : 0xE6E6FA,
214                 MISTYROSE     : 0xFFE4E1,
215                 IVORY         : 0xFFFFF0,
216                 LEMONCHIFFON  : 0xFFFACD
217         },
218         
219         PARAMS : ( function(){
220                 var ret = {};
221                 register( ret.percent = {},
222                         'marginBottom,marginLeft,marginRight,marginTop,paddingBottom,paddingLeft,paddingRight,paddingTop,fontSize,textIndent'
223                 );
224                 register( ret.offset = {},
225                         'height,width,bottom,left,right,top'
226                 );              
227                 register( ret.size = {},
228                         'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth,letterSpacing,wordSpacing'
229                 );
230                 register( ret.color = {},
231                         'backgroundColor,borderBottomColor,borderLeftColor,borderRightColor,borderTopColor,color'
232                 );
233                 register( ret.region = {},
234                         'margin,padding,borderWidth,borderColor'
235                 );              
236                 register( ret.special = {},
237                         'clip,backgroundPosition,backgroundPositionX,backgroundPositionY,opacity,lineHeight,zIndex'
238                 );
239                 register( ret.unit = {}, 'px,cm,mm,in,pt,pc,em,%' );
240                 
241                 register( ret.margin = {}, 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom' );
242                 register( ret.padding = {}, 'paddingBottom,paddingLeft,paddingRight,paddingTop' );
243                 register( ret.borderWidth = {}, 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth' );
244                 register( ret.borderColor = {}, 'borderBottomColor,borderLeftColor,borderRightColor,borderTopColor' );
245                 
246                 function register( obj, params ){
247                         params = params.split( ',' );
248                         for( var i = params.length; i; ) obj[ params[ --i ] ] = true;
249                 };
250                 return ret;
251         })(),
252         
253         _CLIP_SEPARATOR : X.UA.IE && X.UA.IE < 8 ? ' ' : ',',
254         
255         /*
256          * 
257          */
258         Property : X.Class.create(
259                 'Property',
260                 X.Class.POOL_OBJECT,
261                 {
262                         Constructor : function( name, value, unit, xnode ){
263                                 this.name  = name;
264                                 this.value = value;
265                                 this.unit  = unit;
266                                 this.xnode = xnode;
267                         },
268                         name    : '',
269                         value   : 0,
270                         unit    : '',
271                         xnode   : null,
272                         equal : function( prop ){
273                                 if( this.unit === prop.unit ){
274                                         return this.value === prop.value;
275                                 };
276                                 return Math.abs( this.toPx() - prop.toPx() ) < 1;
277                         },
278                         convert: function( prop ){
279                                 var u = prop.unit, v;
280                                 if( this.unit === u ) return;
281                                 this.value = v = this.toPx();
282                                 this.unit  = u;
283                                 // %
284                                 // bgpX, bgpY の場合 X.Dom.Image.getActualDimension( backgroundImage url を使用 )
285                                 if( u !== 'px' ){
286                                         this.value =
287                                                 u === 'em' ?
288                                                         v / this.xnode._getCharSize() :
289                                                         v / ( X.Dom.Style._UNIT_RATIO[ u ] || 1 );
290                                 };
291                         },
292                         setValue: function( v ){
293                                 this.value = v;
294                         },
295                         getValue: function(){
296                                 return this.value;
297                         },
298                         getOffset: function( prop ){
299                                 return prop.value - this.value;
300                         },
301                         getUnit: function(){
302                                 return this.unit;
303                         },
304                         getValueText: function(){
305                                 return this.value === 0 ? '0' : this.value + this.unit;
306                         },
307                         toPx: function(){
308                                 var v = this.value, u = this.unit;
309                                 return
310                                         u === 'px' ?
311                                                 v :
312                                         ( u === 'em' || ( u === '' && this.name === 'lineHeight' ) ) ?
313                                                 v * this.xnode._getCharSize() :
314                                         // u === '%'
315                                                 v / ( X.Dom.Style._UNIT_RATIO[ u ] || 1 );
316                         },
317                         isValid: function(){
318                                 var p = X.Dom.Style.PARAMS,
319                                         n = this.name,
320                                         v = this.value,
321                                         u = this.unit,
322                                         z = u !== '' ? true : v === 0;
323                                 if( p.percent[ n ] === true ) return z;
324                                 if( p.offset[ n ]  === true ) return z;
325                                 if( p.size[ n ]    === true ) return z && u !== '%';
326                                 if( p.special[ n ] === true ){
327                                         if( n === 'lineHeight' ) return true;
328                                         if( n === 'opacity' )    return 0 <= v && v <= 1 && u === '';
329                                         if( n === 'zIndex'  )    return u === '';
330                                 };
331                                 return false;
332                         }
333                 }
334         ),
335         
336         /**
337          * backgroundPosition, clip
338          */
339         PropertyGroup : X.Class.create(
340                 'PropertyGroup',
341                 X.Class.POOL_OBJECT,
342                 {
343                         Constructor : function( name ){
344                                 this.name  = name;
345                                 this.props = [];
346                                 for( var i = 1, l = arguments.length; i<l; ++i ){
347                                         this.props[ this.props.length ] = arguments[ i ];
348                                 };
349                         },
350                         name  : '',
351                         equal : function( prop ){
352                                 var ps = this.props, i = ps.length;
353                                 for( ; i; ){
354                                         --i;
355                                         if( ps[ i ].equal( prop[ i ] ) === false ) return false;
356                                 };
357                                 return true;
358                         },
359                         convert : function( prop ){
360                                 var ps = this.props, i = ps.length;
361                                 for( ; i; ){
362                                         --i;
363                                         ps[ i ].convert( prop[ i ] );
364                                 };
365                         },
366                         setValue : function( ary ){
367                                 var ps = this.props, i = 0, l = ps.length;
368                                 for( ; i<l; ++i ){
369                                         ps[ i ].setValue( ary[ i ] );
370                                 };
371                         },
372                         getValue : function(){
373                                 var ret = [], ps = this.props, i = 0, l = ps.length;
374                                 for( ; i<l; ++i ){
375                                         ret[ ret.length ] = ps[ i ].getValue();
376                                 };
377                                 return ret;
378                         },
379                         getOffset : function( prop ){
380                                 var ret = [],
381                                         ps  = this.props,
382                                         _ps = prop.props,
383                                         i   = 0,
384                                         l = ps.length;
385                                 for( ; i<l; ++i ){
386                                         ret[ ret.length ] = ps[ i ].getOffset( _ps[ i ] );
387                                 };
388                                 return ret;
389                         },
390                         getUnit : function(){
391                                 var ret = [], ps = this.props, i = 0, l = ps.length;
392                                 for( ; i<l; ++i ){
393                                         ret[ ret.length ] = ps[ i ].getUnit();
394                                 };
395                                 return ret;
396                         },
397                         getValueText : function(){
398                                 var ret = [], ps = this.props, i = 0, l = ps.length;
399                                 for( ; i<l; ++i ){
400                                         ret[ ret.length ] = ps[ i ].getValueText();
401                                 };
402                                 if( this.name === 'clip' ){
403                                         return 'rect(' + ret.join( X.Dom.Style._CLIP_SEPARATOR ) + ')';
404                                 };
405                                 return ret.join( ' ' );
406                         },
407                         onKill : function(){
408                                 var ps = this.props, i = ps.length;
409                                 for( ; i; ){
410                                         ps[ --i ].kill();
411                                 };
412                         },
413                         isValid : function( t ){
414                                 t = t || this;
415                                 var ps = t.props, i = ps.length;
416                                 for( ; i; ){
417                                         if( ps[ --i ].isValid() === false ) return false;
418                                 };
419                                 return true;
420                         }
421                 }
422         ),
423
424         /*
425          * http://css-eblog.com/ie-css-problems/rgba-pe.html
426          * ie67 では rgb() は background-color で反応しない、、、
427          */
428
429         ColorProperty : X.Class.create(
430                 'ColorProperty',
431                 X.Class.POOL_OBJECT, {
432                         Constructor : function( name, x ){
433                                 var pct = false,
434                                         r   = 0,
435                                         g   = 0,
436                                         b   = 0,
437                                         a   = 1,
438                                         rgb;
439                                 if( X.Type.isNumber( rgb = x ) || X.Type.isNumber( rgb = X.Dom.Style.COLOR[ x.toUpperCase() ] ) ){
440                                         r = ( rgb & 0xff0000 ) >> 16;
441                                         g = ( rgb & 0xff00 ) >> 8;
442                                         b = ( rgb & 0xff );
443                                 } else
444                                 if( x.charAt( 0 ) === '#' ){
445                                         if( x.length === 7 ){
446                                                 r = parseInt( x.charAt( 1 ) + x.charAt( 2 ), 16 );
447                                                 g = parseInt( x.charAt( 3 ) + x.charAt( 4 ), 16 );
448                                                 b = parseInt( x.charAt( 5 ) + x.charAt( 6 ), 16 );
449                                         } else                  
450                                         if( x.length === 4 ){
451                                                 r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
452                                                 g = parseInt( x.charAt( 2 ) + x.charAt( 2 ), 16 );
453                                                 b = parseInt( x.charAt( 3 ) + x.charAt( 3 ), 16 );
454                                         } else
455                                         if( x.length === 2 ){
456                                                 r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
457                                                 g = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
458                                                 b = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
459                                         };
460                                 } else
461                                 if( x.indexOf( 'rgb(' ) === 0 ){
462                                         rgb = x.substr( 4 ).split( ',' );
463                                         r = parseFloat( rgb[ 0 ] );
464                                         g = parseFloat( rgb[ 1 ] );
465                                         b = parseFloat( rgb[ 2 ] );
466                                         if( x.indexOf( '%' ) !== -1 ) pct = true;
467                                 } else
468                                 if( x.indexOf( 'rgba(' ) === 0 ){
469                                         rgb = x.substr( 5 ).split( ',' );
470                                         r = parseFloat( rgb[ 0 ] );
471                                         g = parseFloat( rgb[ 1 ] );
472                                         b = parseFloat( rgb[ 2 ] );
473                                         a = parseFloat( rgb[ 3 ] );
474                                         if( x.indexOf( '%' ) !== -1 ) pct = true;
475                                 } else {
476                                         r = 255;
477                                         g = 255;
478                                         b = 255;
479                                 };
480                                 
481                                 this.name = name;
482                                 this.r    = r;
483                                 this.g    = g;
484                                 this.b    = b;
485                                 this.a    = a;
486                                 this.pct  = pct;
487                         },
488                         name  : '',
489                         r     : 0,
490                         g     : 0,
491                         b     : 0,
492                         a     : 0,
493                         pct   : false,
494                         equal : function( prop ){
495                                 if( this.pct === prop.pct ){
496                                         return this.r === prop.r && this.g === prop.g && this.b === prop.b;
497                                 };
498                                 var rgb  = this._toPct(),
499                                         _rgb = prop._toPct(),
500                                         i    = rgb.length;
501                                 for( ; i; ){
502                                         --i;
503                                         if( Math.abs( rgb[ i ] - _rgb[ i ] ) > 1 ) return false;
504                                 };
505                                 return true;
506                         },
507                         convert : function( prop ){
508                                 var u = prop.pct, x;
509                                 if( this.pct === u ) return;
510                                 x = u === true ? 100 / 255 : 2.55;
511                                 this.r  *= x;
512                                 this.g  *= x;
513                                 this.b  *= x;
514                                 this.pct = u;
515                         },
516                         setValue : function( rgb ){
517                                 this.r = rgb[ 0 ];
518                                 this.g = rgb[ 1 ];
519                                 this.b = rgb[ 2 ];
520                         },
521                         getValue : function(){
522                                 return [ this.r, this.g, this.b ];
523                         },
524                         getOffset : function( prop ){
525                                 return [ prop.r - this.r, prop.g - this.g, prop.b - this.b ];
526                         },
527                         getUnit : function(){
528                                 return this.pct === true ? '%' : '';
529                         },
530                         getValueText : function(){
531                                 if( this.pct === true ){
532                                         return [ 'rgb(', this.r, '%,', this.g, '%,', this.b, '%)' ].join( '' );
533                                 };
534                                 var round = Math.round;
535                                 
536                                 var rgb   = '00000' + ( ( round( this.r ) << 16 ) + ( round( this.g ) << 8 ) + round( this.b ) ).toString( 16 );
537                                 return '#' + rgb.substr( rgb.length - 6 );
538                         },
539                         _toPct : function(){
540                                 if( this.pct === true ) return [ this.r, this.g, this.b ];
541                                 return [ this.r / 2.55, this.g / 2.55, this.b / 2.55 ];
542                         },
543                         isValid : function( t ){
544                                 var isFinite = window.isFinite;
545                                 if( !isFinite( this.r ) || !isFinite( this.g ) || !isFinite( this.b ) ) return false;
546                                 if( 0 > this.r || 0 > this.g || 0 > this.b ) return false;
547                                 if( this.pct === true ) return this.r <= 100 && this.g <= 100 && this.b <= 100;
548                                 return this.r <= 255 && this.g <= 255 && this.b <= 255;
549                         }
550                 }
551         ),
552         
553         _getProperty : function( xnode, css, unit, p ){
554                 
555                 var XDomStyle     = X.Dom.Style,
556                         me            = XDomStyle._getProperty,
557                         PARAMS        = XDomStyle.PARAMS,
558                         PropertyGroup = XDomStyle.PropertyGroup,
559                         Property      = XDomStyle.Property,
560                         ColorProperty = XDomStyle.ColorProperty,
561                         name, width;
562                 
563                 if( PARAMS.special[ p ] === true || PARAMS.region[ p ] === true ){
564                         switch( p ){
565                                 case 'clip' :
566                                         // rect(...)    クリップします。<top>, <bottom> は上端からの、 <right>, <left> は左端からのオフセットで指定します。Internet Explorer 4~7 では、カンマの代わりにスペースで区切る必要があります。
567                                         // position:absolute または position:fixed を適用した要素に対してのみ有効です。
568                                         var top    = me( p + 'Top' ),
569                                                 right  = me( p + 'Right' ),
570                                                 bottom = me( p + 'Bottom' ),
571                                                 left   = me( p + 'Left' ),
572                                                 ret    = new PropertyGroup( p, top, right, bottom, left ),
573                                     all;
574                                         if( ret.isValid() === true ) return ret;
575                                         ret.kill();
576                                         all = css[ p ].split( '(' )[ 1 ].split( ')' )[ 0 ].split( XDomStyle._CLIP_SEPARATOR );
577                                         return
578                                                 new PropertyGroup( 
579                                                         p,
580                                                         new Property( p + 'Top',    all[ 0 ], 'px', xnode ),
581                                                         new Property( p + 'Right',  all[ 1 ], 'px', xnode ),
582                                                         new Property( p + 'Bottom', all[ 2 ], 'px', xnode ),
583                                                         new Property( p + 'Left',   all[ 3 ], 'px', xnode )
584                                                 );
585
586                                 case 'margin' :
587                                 case 'padding' :
588                                         name  = p;
589                                         width = '';
590                                 case 'borderWidth' :
591                                         var props  = '$1Top$2,$1Right$2,$1Bottom$2,$1Left$2'.split( '$1' ).join( name || 'border' ).split( '$2' ).join( width || 'Width' ).split( ',' ),
592                                                 top    = me( props[ 0 ] ),
593                                                 right  = me( props[ 1 ] ),
594                                                 bottom = me( props[ 2 ] ),
595                                                 left   = me( props[ 3 ] ),
596                                                 ret    = new PropertyGroup( p, top, right, bottom, left ),
597                                                 all, _0, _1, _2, _3, vu, v, u;
598                                         if( ret.isValid() === true ) return ret;
599                                         ret.kill();
600                                         all = css[ p ].split( ' ' );
601                                         _0  = all[ 0 ];
602                                         _1  = all[ 1 ];
603                                         _2  = all[ 2 ];
604                                         _3  = all[ 3 ];
605                                         vu  = XDomStyle._Util._splitValueAndUnit( _0 );
606                                         v   = vu[ 0 ];
607                                         u   = vu[ 1 ];
608                                         switch( all.length ){
609                                                 case 1 :
610                                                         top    = new Property( props[ 0 ], v, u, xnode );
611                                                         right  = new Property( props[ 1 ], v, u, xnode );
612                                                         bottom = new Property( props[ 2 ], v, u, xnode );
613                                                         left   = new Property( props[ 3 ], v, u, xnode );
614                                                         break;
615                                                 case 2 :
616                                                         top    = new Property( props[ 0 ], v, u, xnode );
617                                                         bottom = new Property( props[ 2 ], v, u, xnode );
618                                                         vu     = XDomStyle._Util._splitValueAndUnit( _1 );
619                                                         v      = vu[ 0 ];
620                                                         u      = vu[ 1 ];
621                                                         right  = new Property( props[ 1 ], v, u, xnode );
622                                                         left   = new Property( props[ 3 ], v, u, xnode );
623                                                         break;
624                                                 case 3 :
625                                                         top    = new Property( props[ 0 ], v, u, xnode );
626                                                         vu     = XDomStyle._Util._splitValueAndUnit( _1 );
627                                                         v      = vu[ 0 ];
628                                                         u      = vu[ 1 ];
629                                                         right  = new Property( props[ 1 ], v, u, xnode );
630                                                         left   = new Property( props[ 3 ], v, u, xnode );
631                                                         vu     = XDomStyle._Util._splitValueAndUnit( _2 );
632                                                         v      = vu[ 0 ];
633                                                         u      = vu[ 1 ];
634                                                         bottom = new Property( props[ 2 ], v, u, xnode );
635                                                         break;
636                                                 case 4 :
637                                                         top    = new Property( props[ 0 ], v, u, xnode );
638                                                         vu     = XDomStyle._Util._splitValueAndUnit( _1 );
639                                                         v      = vu[ 0 ];
640                                                         u      = vu[ 1 ];
641                                                         right  = new Property( props[ 1 ], v, u, xnode );
642                                                         vu     = XDomStyle._Util._splitValueAndUnit( _2 );
643                                                         v      = vu[ 0 ];
644                                                         u      = vu[ 1 ];
645                                                         bottom = new Property( props[ 2 ], v,u, xnode );
646                                                         vu     = XDomStyle._Util._splitValueAndUnit( _3 );
647                                                         v      = vu[ 0 ];
648                                                         u      = vu[ 1 ];
649                                                         left   = new Property( props[ 3 ], v, u, xnode );
650                                                         break;
651                                         };
652                                         return new PropertyGroup( p, top, right, bottom, left );
653
654                                 case 'borderColor' :
655                                         var props  = 'borderTopColor,borderRightColor,borderBottomColor,borderLeftColor'.split( ',' ),
656                                                 top    = me( props[ 0 ] ),
657                                                 right  = me( props[ 1 ] ),
658                                                 bottom = me( props[ 2 ] ),
659                                                 left   = me( props[ 3 ] ),
660                                                 ret    = new PropertyGroup( p, top, right, bottom, left ),
661                                                 all, _0, _1;
662                                         if( ret.isValid() === true ) return ret;
663                                         ret.kill();
664                                         all = css[ p ].split( ' ' );
665                                         _0  = all[ 0 ];
666                                         _1  = all[ 1 ];
667                                         switch( all.length ){
668                                                 case 1 :
669                                                         top    = new ColorProperty( props[ 0 ], _0 );
670                                                         right  = new ColorProperty( props[ 1 ], _0 );
671                                                         bottom = new ColorProperty( props[ 2 ], _0 );
672                                                         left   = new ColorProperty( props[ 3 ], _0 );
673                                                         break;
674                                                 case 2 :
675                                                         top    = new ColorProperty( props[ 0 ], _0 );
676                                                         right  = new ColorProperty( props[ 1 ], _1 );
677                                                         bottom = new ColorProperty( props[ 2 ], _0 );
678                                                         left   = new ColorProperty( props[ 3 ], _1 );
679                                                         break;
680                                                 case 3 :
681                                                         top    = new ColorProperty( props[ 0 ], _0 );
682                                                         right  = new ColorProperty( props[ 1 ], _1 );
683                                                         bottom = new ColorProperty( props[ 2 ], all[ 2 ] );
684                                                         left   = new ColorProperty( props[ 3 ], _1 );
685                                                         break;
686                                                 case 4 :
687                                                         top    = new ColorProperty( props[ 0 ], _0 );
688                                                         right  = new ColorProperty( props[ 1 ], _1 );
689                                                         bottom = new ColorProperty( props[ 2 ], all[ 2 ] );
690                                                         left   = new ColorProperty( props[ 3 ], all[ 3 ] );
691                                                         break;
692                                         };
693                                         return new PropertyGroup( p, top, right, bottom, left );
694                                         
695                                 case 'backgroundPosition' :
696                                         var x   = me( p + 'X' ),
697                                                 y   = me( p + 'Y' ),
698                                                 ret = new PropertyGroup( p, x, y ),
699                                                 xy;
700                                         if( ret.isValid() === true ) return ret;
701                                         ret.kill();
702                                         xy = css[ p ].split( ' ' );
703                                         x  = XDomStyle._Util._splitValueAndUnit( xy[ 0 ] );
704                                         y  = XDomStyle._Util._splitValueAndUnit( xy[ 1 ] );
705                                         return
706                                                 new PropertyGroup(
707                                                         p,
708                                                         new Property( p + 'X', x[ 0 ], x[ 1 ], xnode ),
709                                                         new Property( p + 'Y', y[ 0 ], y[ 1 ], xnode )
710                                                 );
711                         };
712                         // opacity, zindex, lineHeight
713                         vu = XDomStyle._Util._splitValueAndUnit( css[ p ] );
714                         return new Property( p, vu[ 0 ], vu[ 1 ], xnode );
715                 };
716                 var x = css[ p ], e, v, u;
717                 /*
718                 if( PARAMS.offset[ p ] === true ){
719                         return new Property( p, vu[ 0 ], vu[ 1 ], xnode );
720
721                         e = this.elm;
722                         if( p === 'width'  ) v = e.offsetWidth;
723                         if( p === 'height' ) v = e.offsetHeight;
724                         if( p === 'top'    ) v = e.offsetTop;
725                         if( p === 'bottom' ) v = e.offsetBottom;
726                         if( p === 'left'   ) v = e.offsetLeft;
727                         if( p === 'right'  ) v = e.offsetRight;
728                         u = _getUnit( x, p );
729                         // alert( p + XDomStyle._Util.pxTo( v, u ) + u )
730                         return new Property( p, XDomStyle._Util.pxTo( v, u ), u, xnode );
731                 }; */
732                 if( p === 'fontSize' && ( v = XDomStyle._FONT_SIZE_RATIO[ x ] ) ){ // xx-small 等
733                         return new Property( p, v, 'px', xnode );
734                 };
735                 if( PARAMS.offset[ p ] || PARAMS.percent[ p ] || PARAMS.size[ p ] ){
736                         vu = XDomStyle._Util._splitValueAndUnit( x );
737                         return new Property( p, vu[ 0 ], vu[ 1 ], xnode );
738                 };
739
740                 if( PARAMS.color[ p ] ) return new ColorProperty( p, x );
741         },
742         
743         _Util : {
744                 /*
745                 getValue: function( x ){
746                         return X.Type.isString( x ) ? parseInt( x ) :
747                                X.Type.isNumber( x ) ? x : 0;
748                 },
749                 getUnit: function( x, p ){
750                         
751
752         var REG_UINIT      = /.*\d(\w{1,2})?/,
753                 $1             = '$1',
754
755                         
756                         var u;
757                         if( X.Type.isString( x ) === true ){
758                                 u = x.replace( REG_UINIT, $1 );
759                                 if( p === 'lineHeight' ) return u;
760                                 if( PARAMS.unit[ u ] !== true ) return 'px';
761                                 return u;
762                         };
763                         return 'px';
764                 }, */
765                 _splitValueAndUnit : function( v ){
766                         var num, _num, i, u;
767                         if( X.Type.isNumber( v ) ) return [ v || 0, '' ];
768                         if( isNaN( num = parseInt( v ) ) ) return [ 0, '' ];
769                         _num = '' + num;
770                         i = v.indexOf( _num ) + _num.length;
771                         u = v.substr( i );
772                         return [ num, X.Dom.Style.UNIT[ u ] ? u : 'px' ];
773                 }               
774         }
775 };
776
777 X.Dom.Style._GET_VALUE_WITH_UNIT = {
778         borderWidth  : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH,
779         //borderStyle  : X.Dom.Style.Type.QUARTET,
780         borderRadius : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH,
781         margin       : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH  | X.Dom.Style.Type.PERCENT,
782         padding      : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH  | X.Dom.Style.Type.PERCENT,
783         clip         : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH  | X.Dom.Style.Type.PERCENT,
784         
785         backgroundColor    : X.Dom.Style.Type.COLOR,
786         backgroundPosition : X.Dom.Style.Type.COMBI,
787         
788         // boxShadow
789         
790         fontSize      : X.Dom.Style.Type.LENGTH,
791         lineHeight    : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT | X.Dom.Style.Type.NUMERICAL,
792         textIndent    : X.Dom.Style.Type.LENGTH,
793         letterSpacing : X.Dom.Style.Type.LENGTH,
794         wordSpacing   : X.Dom.Style.Type.LENGTH,
795         /*
796         textShadowColor   : X.Dom.Style.Type.COLOR,
797         textShadowOffsetX : X.Dom.Style.Type.LENGTH,
798         textShadowOffsetY : X.Dom.Style.Type.LENGTH,
799         textShadowBlur    : X.Dom.Style.Type.LENGTH, */
800         
801         width         : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
802         height        : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
803         
804         left          : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
805         top           : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
806         bottom        : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
807         right         : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
808         
809         // table
810         borderSpacing : X.Dom.Style.Type.LENGTH
811 };
812
813         
814 X.Dom.Style.SPECIAL_FIX =
815         // ~IE8
816         X.UA.IE && X.UA.IE < 9 ?
817                 (function( obj ){
818                         var test    = X.Dom.Style.SPECIAL_FIX_PROP,
819                                 filters = [], p, id, v;
820                         for( p in obj ){
821                                 if( !( id = test[ p ] ) ) continue;
822                                 v = obj[ p ];
823                                 switch( id ){
824                                         case 1 : //'filter' :
825                                                 filters[ filters.length ] = v;
826                                                 break;
827                                         case 2 : //'opacity' :
828                                                 filters[ filters.length ] = 'aplha(opacity=' + v +')';
829                                                 break;
830                                         case 3 : //'boxShadow' :
831                                                 // box-shadow: 10px 10px 10px 10px rgba(0,0,0,0.4) inset;
832                                                 // スペース区切りで、水平方向の距離 垂直方向の距離 ぼかし距離 広がり距離 影の色 insetキーワードを指定する。 ぼかし距離 広がり距離 影の色 insetキーワードは省略可
833                                                 // shadow(color=#cccccc, strength=10, direction=135);
834                                                 parseValue( 'boxShadow', v, 'px' );
835                                                 dir = Math.atan2( ary[1], ary[0] ) * 180 / Math.PI + 90;
836                                                 dir += dir < 0 ? 360 : 0;
837                                                 break;
838                                         case 4 : //'textShadow' :
839                                                 //text-shadow: 5px 5px 2px blue; 水平方向の距離 垂直方向の距離 影のぼかし半径 影の色 none
840                                                 //glow(Color=yellow,Strength=10);
841                                                 //どうやらCSSのbackgroundプロパティと同時に使えないようです。 
842                                                 break;
843                                         case 5 : //'backgroundImage' :
844                                                 //
845                                 };
846                         };
847                         if( filters ) return filters.join( ' ' );
848                 }) :
849         // IE9 textShadow に filter を使用
850         X.UA.IE && 9 <= X.UA.IE && X.UA.IE < 10 ?
851                 (function( obj ){
852                         var test    = X.Dom.Style.SPECIAL_FIX_PROP,
853                                 filters = [], p, id, v;
854                         for( p in obj ){
855                                 if( !( id = test[ p ] ) ) continue;
856                                 v = obj[ p ];
857                                 switch( id ){
858                                         case 1 : //'filter' :
859                                                 filters[ filters.length ] = v;
860                                                 break;
861                                 };
862                         };
863                         if( filters ) return filters.join( ' ' );
864                 }) :
865                 (function( obj ){
866                         var test    = X.Dom.Style.SPECIAL_FIX_PROP,
867                                 ret = [], p, id, v;
868                         for( p in obj ){
869                                 if( !( id = test[ p ] ) ) continue;
870                                 v = obj[ p ];
871                                 switch( id ){
872                                         case 1 : //'backgroundPositionX' :
873                                                 bgpX = v;
874                                                 break;
875                                         case 2 : //'backgroundPositionY' :
876                                                 bgpY = v;
877                                                 break;
878                                         case 3 : //'backgroundPositionX' :
879                                                 clipT = v;
880                                                 break;
881                                         case 4 : //'backgroundPositionX' :
882                                                 clipB = v;
883                                                 break;
884                                         case 5 : //'backgroundPositionX' :
885                                                 clipL = v;
886                                                 break;
887                                         case 6 : //'backgroundPositionX' :
888                                                 clipR = v;
889                                                 break;
890                                 };
891                         };
892                         if( bgpX || bgpY ) ret[ ret.length ] = 'background-position:';
893                         if( clipT || clipB || clipL || clipR ){
894                                 ret[ ret.length ] = 'clip:rect(';
895                         };
896                         return ret.join( ';' );
897                 });
898
899
900
901
902 // export
903 // name getter
904 // unitID, name 単位指定のプロパティ取得 geter
905 // obj setter
906 // name, value setter
907 X.Dom.Node.prototype.css = function( nameOrObj /* orUnitID, valuOrUnitOrName */ ){
908         var XDomStyle = X.Dom.Style,
909                 args = arguments,
910                 css  = this._css,
911                 p, valOrUnit, name, v, node, camelize, unit;
912         if( this._xnodeType !== 1 ) return this;
913 // setter:object
914         if( X.Type.isObject( nameOrObj ) ){
915                 if( !css ) css = this._css = {};
916                 camelize = XDomStyle.camelize;
917                 for( p in nameOrObj ){
918                         css[ camelize( p ) ] = nameOrObj[ p ];
919                 };
920                 this._cssText = XDomStyle.objToCssText( this._css );
921                 if( node = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode ){
922                         if( this._cssText ){
923                                 node.style.cssText = this._cssText;
924                                 this._styleText = ' style="' + this._cssText + '"';
925                         } else {
926                                 node.removeAttribute( 'style' );
927                                 delete this._cssText;
928                                 delete this._styleText;
929                         };
930                 };
931                 return this;
932         } else
933         if( 1 < args.length ){
934                 if( !( unit = XDomStyle.UNIT[ nameOrObj ] ) ){
935 // setter name, value                   
936                         if( !css ) css = this._css = {};
937                         name = XDomStyle.camelize( nameOrObj );
938                         v    = args[ 1 ];
939                         node = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;
940                         if( css[ name ] === v ) return this;
941                         if( !v && v !== 0 ){
942                                 delete css[ name ];
943                                 if( node ){
944                                         node.style[ name ] = ''; // val
945                                 };
946                                 this._cssText = XDomStyle.objToCssText( css );
947                                 if( !this._cssText ){
948                                         delete this._cssText;
949                                         delete this._styleText;
950                                         node && node.removeAttribute( 'style' );
951                                 };
952                                 return this;
953                         };
954                         if( node ){
955                                 node.style[ name ] = v; // val
956                         };
957                         if( !css[ name ] ){
958                                 this._cssText = [ this._cssText, this._cssText ? ';' : '', XDomStyle.uncamelize( nameOrObj ), ':', v ].join( '' );
959                                 css[ name ] = v;
960                         } else {
961                                 css[ name ] = v;
962                                 this._cssText = XDomStyle.objToCssText( css );
963                         };
964                         this._styleText = ' style="' + this._cssText + '"';
965                         return this;
966                 };
967 // getter unit
968 // unit 付の値取得は fontSize と 画像サイズが確定していないと正確に取れない。内部のみにする?
969                 if( !css ) return;
970                 if( !X.Dom.Style._GET_VALUE_WITH_UNIT[ name = XDomStyle.camelize( args[ 1 ] ) ] ) return null;
971                 p = XDomStyle._getProperty( this, css, unit, name );
972                 v = p.pxTo( unit );
973                 p.kill();
974                 return v;
975         };
976 // getter
977         if( !css ) return;
978         // 集計 border, padding, margin, backgroundPosition, clip
979         // border で正確なデータを返せない時は、null を返す
980         return css[ XDomStyle.camelize( nameOrObj ) ];
981 };
982
983 X.Dom.Node.prototype.cssText = function( v ){
984         var camelize, obj, i, l, attr, name;
985         if( X.Type.isString( v ) ){
986                 camelize = X.Dom.Style.camelize;
987                 obj = {};
988                 v   = v.split( ';' );
989                 delete this._css;
990                 for( i = 0, l = v.length; i < l; ++i ){
991                         attr = v[ i ].split( ':' );
992                         name = camelize( attr[ 0 ] );
993                         name && ( obj[ name ] = attr[ 1 ] || true );
994                 };
995                 return this.css( obj );
996         };
997         return this._cssText;
998 };
999
1000 /*
1001  * ここでは HTMLElement かのチャックは行わない!
1002  */
1003 X.Dom.Node.prototype._getCharSize =
1004         window.getComputedStyle ?
1005                 (function(){
1006                         return parseInt( getComputedStyle( this._rawNode, null ).fontSize );
1007                 }) :
1008         document.defaultView && document.defaultView.getComputedStyle ?
1009                 (function(){
1010                         return parseInt( document.defaultView.getComputedStyle( this._rawNode, null ).fontSize );
1011                 }) :
1012         X.UA.IE && 5 <= X.UA.IE ?
1013                 (function(){
1014                         var font = this._rawNode.currentStyle.fontSize,
1015                                 vu   = X.Dom.Style._Util._splitValueAndUnit( font ),
1016                                 v    = vu[ 0 ],
1017                                 u    = vu[ 1 ];
1018                         switch( u ){
1019                                 case 'px' :
1020                                         return v;
1021                                 case 'em' :
1022                                 // body まで辿ってしまった場合は?
1023                                         return this.parent._getCharSize() * v;
1024                                 case '%' :
1025                                 // body まで辿ってしまった場合は?
1026                                         return this.parent._getCharSize() * v / 100;
1027                         };
1028                         return v === 0 ?
1029                                         ( X.Dom.Style._FONT_SIZE_RATIO[ font ] || 0 ) :
1030                                         v / ( X.Dom.Style._UNIT_RATIO[ u ] || 1 );
1031                         // appendChild
1032                         // removeChild
1033                 }) :
1034         document.removeChild ?
1035                 (function(){
1036                         var elm = document.createElement( 'span' ),
1037                                 v;
1038                         elm.style.cssText = 'display:block;position:absolute;top:0;left:0;visivility:hidden;line-height:1;height:1em;';
1039                         elm.innerHTML = 'X';
1040                         this._rawNode.appendChild( elm );
1041                         v = elm.offsetHeight;
1042                         this._rawNode.removeChild( elm );
1043                         return v;
1044                 }) :
1045         X.UA.IE ?
1046                 (function(){
1047                         var elm = this._rawNode, v;
1048                         elm.insertAdjacentHTML( 'BeforeEnd', '<span style="visivility:hidden;line-height:1;">X</span>' );
1049                         elm = elm.children[ elm.children.length - 1 ];
1050                         v   = elm.offsetHeight;
1051                         elm.outerHTML = '';
1052                         return v;
1053                 }) :
1054                 (function(){
1055                 });
1056
1057
1058 X.Dom.listenOnce( X.Dom.Event.DOM_PRE_INIT, function(){
1059         var testStyle = X.Dom._root;
1060         
1061         X.Dom.Style.VENDER_PREFIX = (function(){
1062                 var ret       = {},
1063                         vendors   = 'webkit,Webkit,Moz,moz,ms,Ms,O,o,khtml,Khtml'.split( ',' ),
1064                         searches  =
1065                                 'opacity,boxSizing,' +
1066                                 'transform,transformOrigin,perspective,' +
1067                                 'transisiton,transitionDelay,transitionProperty,transitionDuration,transitionTimingFunction,' +
1068                                 'userSelect,touchAction,touchCallout,contentZooming,userDrag,tapHighlightColor'.split( ',' ),
1069                         vendor, i, search, prop;
1070                 // 
1071                 vendors.unshift( '' );
1072                 
1073                 function findVenderPrefix( prop ){
1074                         var v, i = vendors.length;
1075                         vendor = null;
1076                         for( ; i; ){
1077                                 v = vendors[ --i ];
1078                                 if( testStyle[ v + prop ] !== undefined ){
1079                                         vendor = v;
1080                                         return v + prop;
1081                                 };
1082                         };      
1083                 };
1084                 
1085                 for( i = searches.length; i; ){
1086                         search = searches[ --i ];
1087                         prop = findVenderPrefix( search );
1088                         if( search === 'transform' ) ret.transVender = vendor;
1089                         if( prop ) ret[ search ] = prop;
1090                 };
1091                 return ret;
1092         })();
1093                 
1094         X.Dom.Style.SPECIAL_FIX_PROP =
1095                 // ~IE8
1096                 X.UA.IE && X.UA.IE < 9 ?
1097                         {
1098                                 filter          : 1,
1099                                 opacity         : 2//, uinode ChromeNode で行う
1100                                 //boxShadow       : 3,
1101                                 //textShadow      : 4,
1102                                 //backgroundImage : 5
1103                         } :
1104                 // IE9
1105                 X.UA.IE && 9 <= X.UA.IE && X.UA.IE < 10 ?
1106                         {
1107                                 filter          : 1//,
1108                                 //textShadow      : 1
1109                         } :
1110                 {
1111                         backgroundPositionX : testStyle.backgroundPositionX === undefined ? 3 : 0,
1112                         backgroundPosiitonY : testStyle.backgroundPositionX === undefined ? 3 : 0,
1113                         clipTop             : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 3 : 0,
1114                         clipBottom          : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 4 : 0,
1115                         clipLeft            : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 5 : 0,
1116                         clipRight           : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 6 : 0
1117                 };
1118 } );
1119
1120 X.Dom.listenOnce( X.Dom.Event.DOM_INIT, function(){
1121         var xnode  = Node._systemNode,
1122                 output = X.Dom.Style._UNIT_RATIO = {},
1123                 list   = 'em,cm,mm,in,pt,pc'.split( ',' ),
1124                 unit,size, base, i;
1125         
1126         for( i = list.length; i; ){
1127                 unit = list[ --i ];
1128                 output[ unit ] = xnode.css( 'width', 100 + unit ).width() / 100;
1129         };
1130
1131         output = X.Dom.Style._FONT_SIZE_RATIO = {},
1132         list   = 'xx-large,x-large,large,larger,medium,small,smaller,x-small,xx-small'.split( ',' );
1133         base   = xnode.css( 'lineHeight', 1 ).text( 'X' ).height();
1134         
1135         for( i = list.length; i; ){
1136                 size = list[ --i ];
1137                 output[ size ] = xnode.css( 'fontSize', size ).height() / base;
1138         };
1139         
1140         xnode.empty().cssText( '' );
1141 } );