4 * style 値の変更は、enterFrame 後にまとめて適用
5 * width(), height(), x(), y() 1em の取得時にも適用
6 * css3 の ie用 fix は X.UI レベルで行う
44 /* font-size -> fontSize */
45 _DICTIONARY_CAMELIZE : {},
47 camelize : function( cssProp ){
49 parts, l, i, camelized;
51 if( camelized = me._DICTIONARY_CAMELIZE[ cssProp ] ) return camelized;
52 parts = cssProp.split( ' ' ).join( '' ).split( '-' );
54 if( l === 1 ) return parts[ 0 ];
56 camelized = cssProp.charAt(0) === '-'
57 ? parts[ 0 ].charAt( 0 ).toUpperCase() + parts[ 0 ].substring( 1 )
60 for( i = 1; i < l; ++i ){
61 camelized += parts[ i ].charAt( 0 ).toUpperCase() + parts[ i ].substring( 1 );
63 return me._DICTIONARY_CAMELIZE[ cssProp ] = camelized;
66 /* fontSize -> font-size */
67 CHAR_CODE_A : 'A'.charCodeAt( 0 ),
69 _DICTIONARY_UNCAMELIZE : {},
71 uncamelize : function( str ){
75 uncamelized, l, chr, code;
76 str = str.split( ' ' ).join( '' );
77 if( uncamelized = me._DICTIONARY_UNCAMELIZE[ str ] ) return uncamelized;
79 for( i = 0, l = str.length; i < l; ++i ){
80 chr = str.charAt( i );
81 code = chr.charCodeAt( 0 );
82 uncamelized += ( A <= code && code <= Z ) ? '-' + chr : chr;
84 return me._DICTIONARY_UNCAMELIZE[ str ] = uncamelized.toLowerCase();
88 * CSS における display, position, float プロパティの相互関係
89 * http://d.hatena.ne.jp/elm200/20080201/1201874740
91 * CSS21:9.7 Relationships between ’display’, ’position’, and ’float’
92 * http://www.w3.org/TR/CSS21/visuren.html#dis-pos-flo
94 * display:none? -yes-> 非表示
96 * position:absolute? -yes-> float:none,display:block;
98 * float:none? -no-> display:block;
103 display position float
104 block static|relative none
105 block static|relative right|left
107 inline static|relative none
114 objToCssText : function( obj ){
117 uncamelize = me.uncamelize,
118 VENDER_PREFIX = me.VENDER_PREFIX,
119 FIX_PROP = me.SPECIAL_FIX_PROP,
120 SPECIAL_FIX = me.SPECIAL_FIX,
123 if( !obj ) return ''; // Opera7.5 未満?
125 // TODO Object が拡張されていると error...
126 name = uncamelize( VENDER_PREFIX[ p ] || p );
127 if( FIX_PROP[ name ] ){
130 css[ ++n ] = [ name, obj[ p ] ].join( ':' );
133 sp && ( css[ ++n ] = 'filter:' + SPECIAL_FIX( obj ) );
134 return css.join( ';' );
138 X.UA.IE && X.UA.IE < 9 && !X.UA.MacIE ?
143 9 <= X.UA.IE && X.UA.IE < 10 ? // == 9
148 _FONT_SIZE_RATIO : null,
150 // https://developer.mozilla.org/en-US/docs/Web/CSS/transform
151 // Firefox 3.5, ie9, Opera 10.5, Safari 3.1, Chrome
152 // 3D support Firefox 10, ie10, Safari 4.0, Chrome 12.0
153 // transform : void 0,
155 // https://developer.mozilla.org/ja/docs/Web/Guide/CSS/Using_CSS_transitions
156 // Chrome 1.0, Firefox 4.0, ie10, Opera 10.5, Safari 3.2
157 // Android 2.1, Firefox Android 4.0, Opera Mobile 10, Safari Mobile 3.2
158 // transition : void 0
160 // ブラウザ毎の getComputedStyle の戻り値 http://d.hatena.ne.jp/uupaa/20080928/1222543331
182 SLATEGRAY : 0x708090,
184 GAINSBORO : 0xDCDCDC,
185 MIDNIGHTBLUE : 0x191970,
186 SLATEBLUE : 0x6A5ACD,
187 MEDIUMBLUE : 0x0000CD,
188 ROYALBLUE : 0x4169E1,
189 DODGERBLUE : 0x1E90FF,
191 STEELBLUE : 0x4682B4,
192 LIGHTBLUE : 0xADD8E6,
193 PALETURQUOISE : 0xAFEEEE,
194 TURQUOISE : 0x40E0D0,
195 LIGHTCYAN : 0xE0FFFF,
196 AQUAMARINE : 0x7FFFD4,
197 DARKGREEN : 0x006400,
199 LIGHTGREEN : 0x90EE90,
200 CHARTREUSE : 0x7FFF00,
201 GREENYELLOW : 0xADFF2F,
202 LIMEGREEN : 0x32CD32,
203 YELLOWGREEN : 0x9ACD32,
204 OLIVEDRAB : 0x6B8E23,
205 DARKKHAKI : 0xBCB76B,
206 PALEGOLDENROD : 0xEEE8AA,
207 LIGHTYELLOW : 0xFFFFE0,
209 GOLDENROD : 0xDAA520,
210 DARKGOLDENROD : 0xB8860B,
211 ROSYBROWN : 0xBC8F8F,
212 INDIANRED : 0xCD5C5C,
213 SADDLEBROWN : 0x8B4513,
216 BURLYWOOD : 0xDEB887,
219 SANDYBROWN : 0xF4A460,
221 CHOCOLATE : 0xD2691E,
222 FIREBRICK : 0xB22222,
231 PALEVIOLETRED : 0xDB7093,
235 DARKVIOLET : 0x9400D3,
236 BLUEVIOLET : 0x8A2BE2,
237 MEDIUMPURPLE : 0x9370DB,
240 MISTYROSE : 0xFFE4E1,
242 LEMONCHIFFON : 0xFFFACD
245 parseColor : function( x ){
248 if( X.Type.isNumber( x ) ){
249 return ( 0x0 <= x && x <= 0xFFFFFF ) ? x : undefined;
251 if( !X.Type.isString( x ) ) return;
253 if( X.Type.isNumber( rgb = X.Dom.Style.COLOR[ x.toUpperCase() ] ) && 0x0 <= rgb && rgb <= 0xFFFFFF ){
256 if( x.charAt( 0 ) === '#' ){
259 r = parseInt( x.substr( 1, 2 ), 16 );
260 g = parseInt( x.substr( 3, 2 ), 16 );
261 b = parseInt( x.substr( 5, 2 ), 16 );
264 r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
265 g = parseInt( x.charAt( 2 ) + x.charAt( 2 ), 16 );
266 b = parseInt( x.charAt( 3 ) + x.charAt( 3 ), 16 );
269 r = g = b = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
275 if( x.indexOf( 'rgb(' ) === 0 ){
276 rgb = x.substr( 4 ).split( ',' );
277 r = parseFloat( rgb[ 0 ] );
278 g = parseFloat( rgb[ 1 ] );
279 b = parseFloat( rgb[ 2 ] );
280 if( x.indexOf( '%' ) !== -1 ){
286 if( x.indexOf( 'rgba(' ) === 0 ){
287 rgb = x.substr( 5 ).split( ',' );
288 r = parseFloat( rgb[ 0 ] );
289 g = parseFloat( rgb[ 1 ] );
290 b = parseFloat( rgb[ 2 ] );
291 //a = parseFloat( rgb[ 3 ] );
292 if( x.indexOf( '%' ) !== -1 ){
300 return isFinite( r + b + g ) ? ( r << 16 ) + ( g << 8 ) + b : undefined;
303 PARAMS : ( function(){
305 register( ret.percent = {},
306 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom,paddingLeft,paddingRight,paddingTop,fontSize,textIndent'
308 register( ret.offset = {},
309 'height,width,bottom,left,right,top'
311 register( ret.size = {},
312 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth,letterSpacing,wordSpacing'
314 register( ret.color = {},
315 'backgroundColor,borderBottomColor,borderLeftColor,borderRightColor,borderTopColor,color'
317 register( ret.region = {},
318 'margin,padding,borderWidth,borderColor'
320 register( ret.special = {},
321 'clip,backgroundPosition,backgroundPositionX,backgroundPositionY,opacity,lineHeight,zIndex'
323 register( ret.unit = {}, 'px,cm,mm,in,pt,pc,em,%' );
325 register( ret.margin = {}, 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom' );
326 register( ret.padding = {}, 'paddingBottom,paddingLeft,paddingRight,paddingTop' );
327 register( ret.borderWidth = {}, 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth' );
328 register( ret.borderColor = {}, 'borderBottomColor,borderLeftColor,borderRightColor,borderTopColor' );
330 function register( obj, params ){
331 params = params.split( ',' );
332 for( var i = params.length; i; ) obj[ params[ --i ] ] = true;
337 _CLIP_SEPARATOR : X.UA.IE && X.UA.IE < 8 ? ' ' : ',',
342 Property : X.Class.create(
346 Constructor : function( name, value, unit, xnode ){
356 equal : function( prop ){
357 if( this.unit === prop.unit ){
358 return this.value === prop.value;
360 return Math.abs( this.toPx() - prop.toPx() ) < 1;
362 convert: function( prop ){
363 var u = prop.unit, v;
364 if( this.unit === u ) return;
365 this.value = v = this.toPx();
368 // bgpX, bgpY の場合 X.Dom.Image.getActualDimension( backgroundImage url を使用 )
372 v / this.xnode._getCharSize() :
373 v / ( X.Dom.Style._UNIT_RATIO[ u ] || 1 );
376 setValue: function( v ){
379 getValue: function(){
382 getOffset: function( prop ){
383 return prop.value - this.value;
388 getValueText: function(){
389 return this.value === 0 ? '0' : this.value + this.unit;
392 var v = this.value, u = this.unit;
396 ( u === 'em' || ( u === '' && this.name === 'lineHeight' ) ) ?
397 v * this.xnode._getCharSize() :
399 v / ( X.Dom.Style._UNIT_RATIO[ u ] || 1 );
402 var p = X.Dom.Style.PARAMS,
406 z = u !== '' ? true : v === 0;
407 if( p.percent[ n ] === true ) return z;
408 if( p.offset[ n ] === true ) return z;
409 if( p.size[ n ] === true ) return z && u !== '%';
410 if( p.special[ n ] === true ){
411 if( n === 'lineHeight' ) return true;
412 if( n === 'opacity' ) return 0 <= v && v <= 1 && u === '';
413 if( n === 'zIndex' ) return u === '';
421 * backgroundPosition, clip
423 PropertyGroup : X.Class.create(
427 Constructor : function( name ){
430 for( var i = 1, l = arguments.length; i<l; ++i ){
431 this.props[ this.props.length ] = arguments[ i ];
435 equal : function( prop ){
436 var ps = this.props, i = ps.length;
439 if( ps[ i ].equal( prop[ i ] ) === false ) return false;
443 convert : function( prop ){
444 var ps = this.props, i = ps.length;
447 ps[ i ].convert( prop[ i ] );
450 setValue : function( ary ){
451 var ps = this.props, i = 0, l = ps.length;
453 ps[ i ].setValue( ary[ i ] );
456 getValue : function(){
457 var ret = [], ps = this.props, i = 0, l = ps.length;
459 ret[ ret.length ] = ps[ i ].getValue();
463 getOffset : function( prop ){
470 ret[ ret.length ] = ps[ i ].getOffset( _ps[ i ] );
474 getUnit : function(){
475 var ret = [], ps = this.props, i = 0, l = ps.length;
477 ret[ ret.length ] = ps[ i ].getUnit();
481 getValueText : function(){
482 var ret = [], ps = this.props, i = 0, l = ps.length;
484 ret[ ret.length ] = ps[ i ].getValueText();
486 if( this.name === 'clip' ){
487 return 'rect(' + ret.join( X.Dom.Style._CLIP_SEPARATOR ) + ')';
489 return ret.join( ' ' );
492 var ps = this.props, i = ps.length;
497 isValid : function( t ){
499 var ps = t.props, i = ps.length;
501 if( ps[ --i ].isValid() === false ) return false;
509 * http://css-eblog.com/ie-css-problems/rgba-pe.html
510 * ie67 では rgb() は background-color で反応しない、、、
513 ColorProperty : X.Class.create(
515 X.Class.POOL_OBJECT, {
516 Constructor : function( name, x ){
523 if( X.Type.isNumber( rgb = x ) || X.Type.isNumber( rgb = X.Dom.Style.COLOR[ x.toUpperCase() ] ) ){
524 r = ( rgb & 0xff0000 ) >> 16;
525 g = ( rgb & 0xff00 ) >> 8;
528 if( x.charAt( 0 ) === '#' ){
529 if( x.length === 7 ){
530 r = parseInt( x.charAt( 1 ) + x.charAt( 2 ), 16 );
531 g = parseInt( x.charAt( 3 ) + x.charAt( 4 ), 16 );
532 b = parseInt( x.charAt( 5 ) + x.charAt( 6 ), 16 );
534 if( x.length === 4 ){
535 r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
536 g = parseInt( x.charAt( 2 ) + x.charAt( 2 ), 16 );
537 b = parseInt( x.charAt( 3 ) + x.charAt( 3 ), 16 );
539 if( x.length === 2 ){
540 r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
541 g = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
542 b = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
545 if( x.indexOf( 'rgb(' ) === 0 ){
546 rgb = x.substr( 4 ).split( ',' );
547 r = parseFloat( rgb[ 0 ] );
548 g = parseFloat( rgb[ 1 ] );
549 b = parseFloat( rgb[ 2 ] );
550 if( x.indexOf( '%' ) !== -1 ) pct = true;
552 if( x.indexOf( 'rgba(' ) === 0 ){
553 rgb = x.substr( 5 ).split( ',' );
554 r = parseFloat( rgb[ 0 ] );
555 g = parseFloat( rgb[ 1 ] );
556 b = parseFloat( rgb[ 2 ] );
557 a = parseFloat( rgb[ 3 ] );
558 if( x.indexOf( '%' ) !== -1 ) pct = true;
578 equal : function( prop ){
579 if( this.pct === prop.pct ){
580 return this.r === prop.r && this.g === prop.g && this.b === prop.b;
582 var rgb = this._toPct(),
583 _rgb = prop._toPct(),
587 if( Math.abs( rgb[ i ] - _rgb[ i ] ) > 1 ) return false;
591 convert : function( prop ){
593 if( this.pct === u ) return;
594 x = u === true ? 100 / 255 : 2.55;
600 setValue : function( rgb ){
605 getValue : function(){
606 return [ this.r, this.g, this.b ];
608 getOffset : function( prop ){
609 return [ prop.r - this.r, prop.g - this.g, prop.b - this.b ];
611 getUnit : function(){
612 return this.pct === true ? '%' : '';
614 getValueText : function(){
615 if( this.pct === true ){
616 return [ 'rgb(', this.r, '%,', this.g, '%,', this.b, '%)' ].join( '' );
618 var round = Math.round;
620 var rgb = '00000' + ( ( round( this.r ) << 16 ) + ( round( this.g ) << 8 ) + round( this.b ) ).toString( 16 );
621 return '#' + rgb.substr( rgb.length - 6 );
624 if( this.pct === true ) return [ this.r, this.g, this.b ];
625 return [ this.r / 2.55, this.g / 2.55, this.b / 2.55 ];
627 isValid : function( t ){
628 var isFinite = window.isFinite;
629 if( !isFinite( this.r ) || !isFinite( this.g ) || !isFinite( this.b ) ) return false;
630 if( 0 > this.r || 0 > this.g || 0 > this.b ) return false;
631 if( this.pct === true ) return this.r <= 100 && this.g <= 100 && this.b <= 100;
632 return this.r <= 255 && this.g <= 255 && this.b <= 255;
637 _getProperty : function( xnode, css, unit, p ){
639 var XDomStyle = X.Dom.Style,
640 me = XDomStyle._getProperty,
641 PARAMS = XDomStyle.PARAMS,
642 PropertyGroup = XDomStyle.PropertyGroup,
643 Property = XDomStyle.Property,
644 ColorProperty = XDomStyle.ColorProperty,
647 if( PARAMS.special[ p ] === true || PARAMS.region[ p ] === true ){
650 // rect(...) クリップします。<top>, <bottom> は上端からの、 <right>, <left> は左端からのオフセットで指定します。Internet Explorer 4~7 では、カンマの代わりにスペースで区切る必要があります。
651 // position:absolute または position:fixed を適用した要素に対してのみ有効です。
652 var top = me( p + 'Top' ),
653 right = me( p + 'Right' ),
654 bottom = me( p + 'Bottom' ),
655 left = me( p + 'Left' ),
656 ret = new PropertyGroup( p, top, right, bottom, left ),
658 if( ret.isValid() === true ) return ret;
660 all = css[ p ].split( '(' )[ 1 ].split( ')' )[ 0 ].split( XDomStyle._CLIP_SEPARATOR );
664 new Property( p + 'Top', all[ 0 ], 'px', xnode ),
665 new Property( p + 'Right', all[ 1 ], 'px', xnode ),
666 new Property( p + 'Bottom', all[ 2 ], 'px', xnode ),
667 new Property( p + 'Left', all[ 3 ], 'px', xnode )
675 var props = '$1Top$2,$1Right$2,$1Bottom$2,$1Left$2'.split( '$1' ).join( name || 'border' ).split( '$2' ).join( width || 'Width' ).split( ',' ),
676 top = me( props[ 0 ] ),
677 right = me( props[ 1 ] ),
678 bottom = me( props[ 2 ] ),
679 left = me( props[ 3 ] ),
680 ret = new PropertyGroup( p, top, right, bottom, left ),
681 all, _0, _1, _2, _3, vu, v, u;
682 if( ret.isValid() === true ) return ret;
684 all = css[ p ].split( ' ' );
689 vu = XDomStyle._splitValueAndUnit( _0 );
692 switch( all.length ){
694 top = new Property( props[ 0 ], v, u, xnode );
695 right = new Property( props[ 1 ], v, u, xnode );
696 bottom = new Property( props[ 2 ], v, u, xnode );
697 left = new Property( props[ 3 ], v, u, xnode );
700 top = new Property( props[ 0 ], v, u, xnode );
701 bottom = new Property( props[ 2 ], v, u, xnode );
702 vu = XDomStyle._splitValueAndUnit( _1 );
705 right = new Property( props[ 1 ], v, u, xnode );
706 left = new Property( props[ 3 ], v, u, xnode );
709 top = new Property( props[ 0 ], v, u, xnode );
710 vu = XDomStyle._splitValueAndUnit( _1 );
713 right = new Property( props[ 1 ], v, u, xnode );
714 left = new Property( props[ 3 ], v, u, xnode );
715 vu = XDomStyle._splitValueAndUnit( _2 );
718 bottom = new Property( props[ 2 ], v, u, xnode );
721 top = new Property( props[ 0 ], v, u, xnode );
722 vu = XDomStyle._splitValueAndUnit( _1 );
725 right = new Property( props[ 1 ], v, u, xnode );
726 vu = XDomStyle._splitValueAndUnit( _2 );
729 bottom = new Property( props[ 2 ], v,u, xnode );
730 vu = XDomStyle._splitValueAndUnit( _3 );
733 left = new Property( props[ 3 ], v, u, xnode );
736 return new PropertyGroup( p, top, right, bottom, left );
739 var props = 'borderTopColor,borderRightColor,borderBottomColor,borderLeftColor'.split( ',' ),
740 top = me( props[ 0 ] ),
741 right = me( props[ 1 ] ),
742 bottom = me( props[ 2 ] ),
743 left = me( props[ 3 ] ),
744 ret = new PropertyGroup( p, top, right, bottom, left ),
746 if( ret.isValid() === true ) return ret;
748 all = css[ p ].split( ' ' );
751 switch( all.length ){
753 top = new ColorProperty( props[ 0 ], _0 );
754 right = new ColorProperty( props[ 1 ], _0 );
755 bottom = new ColorProperty( props[ 2 ], _0 );
756 left = new ColorProperty( props[ 3 ], _0 );
759 top = new ColorProperty( props[ 0 ], _0 );
760 right = new ColorProperty( props[ 1 ], _1 );
761 bottom = new ColorProperty( props[ 2 ], _0 );
762 left = new ColorProperty( props[ 3 ], _1 );
765 top = new ColorProperty( props[ 0 ], _0 );
766 right = new ColorProperty( props[ 1 ], _1 );
767 bottom = new ColorProperty( props[ 2 ], all[ 2 ] );
768 left = new ColorProperty( props[ 3 ], _1 );
771 top = new ColorProperty( props[ 0 ], _0 );
772 right = new ColorProperty( props[ 1 ], _1 );
773 bottom = new ColorProperty( props[ 2 ], all[ 2 ] );
774 left = new ColorProperty( props[ 3 ], all[ 3 ] );
777 return new PropertyGroup( p, top, right, bottom, left );
779 case 'backgroundPosition' :
780 var x = me( p + 'X' ),
782 ret = new PropertyGroup( p, x, y ),
784 if( ret.isValid() === true ) return ret;
786 xy = css[ p ].split( ' ' );
787 x = XDomStyle._splitValueAndUnit( xy[ 0 ] );
788 y = XDomStyle._splitValueAndUnit( xy[ 1 ] );
792 new Property( p + 'X', x[ 0 ], x[ 1 ], xnode ),
793 new Property( p + 'Y', y[ 0 ], y[ 1 ], xnode )
796 // opacity, zindex, lineHeight
797 vu = XDomStyle._splitValueAndUnit( css[ p ] );
798 return new Property( p, vu[ 0 ], vu[ 1 ], xnode );
800 var x = css[ p ], e, v, u;
802 if( PARAMS.offset[ p ] === true ){
803 return new Property( p, vu[ 0 ], vu[ 1 ], xnode );
806 if( p === 'width' ) v = e.offsetWidth;
807 if( p === 'height' ) v = e.offsetHeight;
808 if( p === 'top' ) v = e.offsetTop;
809 if( p === 'bottom' ) v = e.offsetBottom;
810 if( p === 'left' ) v = e.offsetLeft;
811 if( p === 'right' ) v = e.offsetRight;
812 u = _getUnit( x, p );
813 // alert( p + XDomStyle._Util.pxTo( v, u ) + u )
814 return new Property( p, XDomStyle._Util.pxTo( v, u ), u, xnode );
816 if( p === 'fontSize' && ( v = XDomStyle._FONT_SIZE_RATIO[ x ] ) ){ // xx-small 等
817 return new Property( p, v, 'px', xnode );
819 if( PARAMS.offset[ p ] || PARAMS.percent[ p ] || PARAMS.size[ p ] ){
820 vu = XDomStyle._splitValueAndUnit( x );
821 return new Property( p, vu[ 0 ], vu[ 1 ], xnode );
824 if( PARAMS.color[ p ] ) return new ColorProperty( p, x );
827 _splitValueAndUnit : function( v ){
829 if( X.Type.isNumber( v ) ) return [ v || 0, '' ];
830 if( isNaN( num = parseFloat( v ) ) ) return [ 0, '' ];
832 if( _num.indexOf( '0.' ) === 0 ) _num = _num.slice( 1 );
833 u = v.substr( v.indexOf( _num ) + _num.length );
834 return [ num, X.Dom.Style.UNIT[ u ] ? u : 'px' ];
838 X.Dom.Style._GET_VALUE_WITH_UNIT = {
839 borderWidth : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH,
840 //borderStyle : X.Dom.Style.Type.QUARTET,
841 borderRadius : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH,
842 margin : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
843 padding : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
844 clip : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
846 backgroundColor : X.Dom.Style.Type.COLOR,
847 backgroundPosition : X.Dom.Style.Type.COMBI,
851 fontSize : X.Dom.Style.Type.LENGTH,
852 lineHeight : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT | X.Dom.Style.Type.NUMERICAL,
853 textIndent : X.Dom.Style.Type.LENGTH,
854 letterSpacing : X.Dom.Style.Type.LENGTH,
855 wordSpacing : X.Dom.Style.Type.LENGTH,
857 textShadowColor : X.Dom.Style.Type.COLOR,
858 textShadowOffsetX : X.Dom.Style.Type.LENGTH,
859 textShadowOffsetY : X.Dom.Style.Type.LENGTH,
860 textShadowBlur : X.Dom.Style.Type.LENGTH, */
862 width : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
863 height : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
865 left : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
866 top : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
867 bottom : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
868 right : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
871 borderSpacing : X.Dom.Style.Type.LENGTH
875 X.Dom.Style.SPECIAL_FIX =
877 X.UA.IE && X.UA.IE < 9 && !X.UA.MacIE?
879 var test = X.Dom.Style.SPECIAL_FIX_PROP,
884 if( !( id = test[ p ] ) ) continue;
887 case 1 : //'filter' :
890 case 2 : //'opacity' :
891 filters[ ++n ] = 'alpha(opacity=' + v * 100 +')';
893 case 3 : //'boxShadow' :
894 // box-shadow: 10px 10px 10px 10px rgba(0,0,0,0.4) inset;
895 // スペース区切りで、水平方向の距離 垂直方向の距離 ぼかし距離 広がり距離 影の色 insetキーワードを指定する。 ぼかし距離 広がり距離 影の色 insetキーワードは省略可
896 // shadow(color=#cccccc, strength=10, direction=135);
897 v = X.Dom.Style._getProperty( this, css, 'px', 'boxShadow' );
898 dir = Math.atan2( v[ 1 ], v[ 0 ] ) * 180 / Math.PI + 90;
899 dir += dir < 0 ? 360 : 0;
900 filters[ ++n ] = 'shadow(color=' + v[ 4 ] + ',strength=' + v[ 3 ] + ',direction=' + dir + ')';
902 case 4 : //'textShadow' :
903 //text-shadow: 5px 5px 2px blue; 水平方向の距離 垂直方向の距離 影のぼかし半径 影の色 none
904 //glow(Color=yellow,Strength=10);
905 //どうやらCSSのbackgroundプロパティと同時に使えないようです。
909 case 5 : //'backgroundImage' :
913 return filters.join( ' ' );
915 // IE9 textShadow に filter を使用
916 X.UA.IE && 9 <= X.UA.IE && X.UA.IE < 10 ?
918 var test = X.Dom.Style.SPECIAL_FIX_PROP,
919 filters = [], p, id, v;
921 if( !( id = test[ p ] ) ) continue;
924 case 1 : //'filter' :
925 filters[ filters.length ] = v;
929 if( filters ) return filters.join( ' ' );
932 var test = X.Dom.Style.SPECIAL_FIX_PROP,
933 ret = [], p, id, v, bgpX, bgpY, clipT, clipB, clipL, clipR;
935 if( !( id = test[ p ] ) ) continue;
938 case 1 : //'backgroundPositionX' :
941 case 2 : //'backgroundPositionY' :
944 case 3 : //'backgroundPositionX' :
947 case 4 : //'backgroundPositionX' :
950 case 5 : //'backgroundPositionX' :
953 case 6 : //'backgroundPositionX' :
958 if( bgpX || bgpY ) ret[ ret.length ] = 'background-position:';
959 if( clipT || clipB || clipL || clipR ){
960 ret[ ret.length ] = 'clip:rect(';
962 return ret.join( ';' );
970 // unitID, name 単位指定のプロパティ取得 geter
972 // name, value setter
974 X.Dom.Node.prototype.css = function( nameOrObj /* orUnitID, valuOrUnitOrName */ ){
975 var XDomStyle = X.Dom.Style,
978 p, name, v, camelize, unit, ieFix;
979 if( this._xnodeType !== 1 ) return this;
981 if( X.Type.isObject( nameOrObj ) ){
982 if( !css ) css = this._css = {};
983 camelize = XDomStyle.camelize;
984 ieFix = X.Dom.Style.IE_FILTER_FIX;
985 for( p in nameOrObj ){
987 this._dirty |= X.Dom.Dirty.IE_FILTER;
990 v || v === 0 ? css[ camelize( p ) ] = v : delete css[ camelize( p ) ];
991 if( p === 'display' ){
992 v === 'none' ? ( this._state |= X.Dom.State.IE5_DISPLAY_NONE_FIX ) : ( this._state &= ~X.Dom.State.IE5_DISPLAY_NONE_FIX );
993 v === 'none' ? ( this._state |= X.Dom.State.DISPLAY_NONE ) : ( this._state &= ~X.Dom.State.DISPLAY_NONE );
996 this._dirty |= X.Dom.Dirty.CSS;
997 this.parent && this._reserveUpdate();
998 delete this._cssText;
1001 if( 1 < args.length ){
1002 if( !XDomStyle.UNIT[ nameOrObj ] ){
1003 // setter name, value
1004 if( !css ) css = this._css = {};
1005 name = XDomStyle.camelize( nameOrObj );
1007 if( css[ name ] === v ) return this;
1008 if( X.Dom.Style.IE_FILTER_FIX[ name ] ){
1009 this._dirty |= X.Dom.Dirty.IE_FILTER;
1011 if( !v && v !== 0 ){
1016 delete this._cssText;
1017 this._dirty |= X.Dom.Dirty.CSS;
1018 if( name === 'display' ){
1019 v === 'none' ? ( this._state |= X.Dom.State.IE5_DISPLAY_NONE_FIX ) : ( this._state &= ~X.Dom.State.IE5_DISPLAY_NONE_FIX );
1020 v === 'none' ? ( this._state |= X.Dom.State.DISPLAY_NONE ) : ( this._state &= ~X.Dom.State.DISPLAY_NONE );
1022 // parent でなく this._root! でなくて this._state & in tree
1023 this.parent && this._reserveUpdate();
1027 // unit 付の値取得は fontSize と 画像サイズが確定していないと正確に取れない。内部のみにする?
1029 if( !XDomStyle._GET_VALUE_WITH_UNIT[ name = XDomStyle.camelize( args[ 1 ] ) ] ) return null;
1030 p = XDomStyle._getProperty( this, css, nameOrObj, name );
1031 v = p.pxTo( nameOrObj );
1037 // 集計 border, padding, margin, backgroundPosition, clip
1038 // border で正確なデータを返せない時は、null を返す
1039 return css[ XDomStyle.camelize( nameOrObj ) ];
1042 X.Dom.Node.prototype.cssText = function( v ){
1043 var obj, i, l, attr, name;
1046 this._state &= ~X.Dom.State.IE5_DISPLAY_NONE_FIX;
1047 this._dirty |= X.Dom.Dirty.CSS;
1048 this.parent && this._reserveUpdate();
1049 delete this._cssText;
1052 if( X.Type.isString( v ) ){
1054 this._state &= ~X.Dom.State.IE5_DISPLAY_NONE_FIX;
1057 for( i = 0, l = v.length; i < l; ++i ){
1058 attr = v[ i ].split( ':' );
1059 ( name = attr[ 0 ] ) && ( obj[ name ] = attr[ 1 ] || true );
1061 return this.css( obj );
1064 if( this._dirty & X.Dom.Dirty.CSS && !( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){
1065 delete this._cssText;
1067 return this._cssText;
1071 * ここでは HTMLElement のチ1ェックは行わない!
1073 * body に css attr がセットされた場合には X.Dom.baseFontSize をクリア
1076 X.Dom.Node.prototype._getCharSize =
1077 window.getComputedStyle ?
1079 Node._body._updateTimerID && Node._body._startUpdate();
1080 if( this === Node._body && X.Dom.baseFontSize ) return X.Dom.baseFontSize;
1081 if( this._fontSize ) return this._fontSize;
1082 return this._fontSize = parseFloat( getComputedStyle( this._rawNode, null ).fontSize );
1084 document.defaultView && document.defaultView.getComputedStyle ?
1086 Node._body._updateTimerID && Node._body._startUpdate();
1087 if( this === Node._body && X.Dom.baseFontSize ) return X.Dom.baseFontSize;
1088 if( this._fontSize ) return this._fontSize;
1089 return this._fontSize = parseFloat( document.defaultView.getComputedStyle( this._rawNode, null ).fontSize );
1091 X.UA.IE && 5.5 <= X.UA.IE ?
1093 var font, vu, v, u, _v;
1094 Node._body._updateTimerID && Node._body._startUpdate();
1095 if( this === Node._body && X.Dom.baseFontSize ) return X.Dom.baseFontSize;
1096 if( this._fontSize ) return this._fontSize;
1098 font = this._rawNode.currentStyle.fontSize;
1099 //font = this._css && this._css.fontSize || '1em';
1100 vu = X.Dom.Style._splitValueAndUnit( font );
1105 if( v = X.Dom.Style._FONT_SIZE_RATIO[ font ] ) return this._fontSize = v;
1107 if( _v = X.Dom.Style._UNIT_RATIO[ u ] ) return this._fontSize = v / _v;
1111 return this._fontSize = v;
1113 // body まで辿ってしまった場合は?
1114 if( this.parent ) return this._fontSize = this.parent._getCharSize() * v;
1117 // body まで辿ってしまった場合は?
1118 if( this.parent ) return this._fontSize = this.parent._getCharSize() * v / 100;
1125 Node._body._updateTimerID && Node._body._startUpdate();
1126 if( this === Node._body && X.Dom.baseFontSize ) return X.Dom.baseFontSize;
1127 if( this._fontSize ) return this._fontSize;
1129 this._rawNode.appendChild( elm = document.createElement( 'span' ) );
1130 elm.style.cssText = 'display:block;position:absolute;top:0;left:0;visivility:hidden;line-height:1;height:1em;';
1131 elm.innerHTML = 'X';
1132 v = elm.offsetHeight;
1133 this._rawNode.removeChild( elm );
1134 return this._fontSize = v;
1138 var font, vu, v, u, _v;
1139 Node._body._updateTimerID && Node._body._startUpdate();
1140 if( this === Node._body && X.Dom.baseFontSize ) return X.Dom.baseFontSize;
1141 if( this._fontSize ) return this._fontSize;
1143 if( this._css && ( font = this._css.fontSize ) ){
1144 vu = X.Dom.Style._splitValueAndUnit( font );
1149 if( _v = X.Dom.Style._FONT_SIZE_RATIO[ font ] ) return this._fontSize = _v;
1151 if( _v = X.Dom.Style._UNIT_RATIO[ u ] ) return this._fontSize = v / _v;
1160 return this._fontSize = v;
1162 // body まで辿ってしまった場合は?
1163 if( this.parent ) return this._fontSize = this.parent._getCharSize() * v;
1166 // body まで辿ってしまった場合は?
1167 if( this.parent ) return this._fontSize = this.parent._getCharSize() * v / 100;
1173 if( this === Node._body && X.Dom.baseFontSize ) return X.Dom.baseFontSize;
1174 Node._body._updateTimerID && Node._body._startUpdate();
1175 if( this._fontSize ) return this._fontSize;
1177 elm = this._rawNode || this._ie4getRawNode();
1178 elm.insertAdjacentHTML( 'BeforeEnd', '<span style="visivility:hidden;line-height:1;">X</span>' );
1179 elm = elm.children[ elm.children.length - 1 ];
1180 v = elm.offsetHeight;
1182 return this._fontSize = v * 0.75;
1186 X.Dom.listenOnce( X.Dom.Event.DOM_PRE_INIT, function(){
1187 var testStyle = X.Dom._root.style,
1188 temp = testStyle.cssText;
1190 X.Dom.Style.VENDER_PREFIX = (function(){
1192 vendors = 'webkit,Webkit,Moz,moz,Ms,ms,O,o,khtml,Khtml'.split( ',' ),
1194 'opacity,boxSizing,' +
1195 'transform,transformOrigin,perspective,' +
1196 'transisiton,transitionDelay,transitionProperty,transitionDuration,transitionTimingFunction,' +
1197 'userSelect,touchSelect,touchAction,touchCallout,contentZooming,userDrag,tapHighlightColor' ).split( ',' ),
1198 vendor, i, search, prop, j, v;
1200 for( i = searches.length; i; ){
1201 search = prop = searches[ --i ];
1203 if( testStyle[ prop ] === undefined ){
1204 prop = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 );
1205 for( j = vendors.length; j; ){
1207 if( testStyle[ v + prop ] !== undefined ){
1208 if( v === 'ms' ) v = 'Ms';// for ie9
1209 if( v === 'o' ) v = 'O';//for opera12
1210 ret[ search ] = v + prop;
1215 ret[ search ] = prop;
1221 testStyle.cssText = 'background:rgba(0,0,0,0.5)';
1223 X.Dom.Style.Support = {
1224 rgba : !!testStyle.background
1227 testStyle.cssText = temp;
1229 X.Dom.Style.SPECIAL_FIX_PROP =
1231 X.UA.IE < 9 && !X.UA.MacIE ?
1234 opacity : 2//, uinode ChromeNode で行う
1237 //backgroundImage : 5
1240 9 <= X.UA.IE && X.UA.IE < 10 ?
1246 backgroundPositionX : testStyle.backgroundPositionX === undefined ? 3 : 0,
1247 backgroundPosiitonY : testStyle.backgroundPositionX === undefined ? 3 : 0,
1248 clipTop : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 3 : 0,
1249 clipBottom : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 4 : 0,
1250 clipLeft : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 5 : 0,
1251 clipRight : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 6 : 0
1255 X.Dom.listenOnce( X.Dom.Event.DOM_INIT, function(){
1256 var xnode = Node._systemNode,
1257 output = X.Dom.Style._UNIT_RATIO = {},
1258 list = 'cm,mm,in,pt,pc'.split( ',' ),
1261 for( i = list.length; i; ){
1263 output[ unit ] = xnode.css( 'width', 10 + unit ).width() / 10;
1266 output = X.Dom.Style._FONT_SIZE_RATIO = {},
1267 list = 'xx-large,x-large,large,larger,medium,small,smaller,x-small,xx-small'.split( ',' );
1268 xnode.css( { lineHeight : '100%', height : '1em' } ).text( 'X' );
1270 for( i = list.length; i; ){
1272 output[ size ] = xnode.css( 'fontSize', size ).height();// / base;
1275 xnode.cssText( '' ).empty();