4 * style 値の変更は、enterFrame 後にまとめて適用
5 * width(), height(), x(), y() 1em の取得時にも適用
6 * css3 の ie用 fix は X.UI レベルで行う
30 AUTO : Number.POSITIVE_INFINITY,
31 FULL : X.Dom // something unigue value; 100%
52 /* font-size -> fontSize */
53 _DICTIONARY_CAMELIZE : {},
55 camelize : function( cssProp ){
57 parts, l, i, camelized;
59 if( camelized = me._DICTIONARY_CAMELIZE[ cssProp ] ) return camelized;
60 parts = cssProp.split( ' ' ).join( '' ).split( '-' );
62 if( l === 1 ) return parts[ 0 ];
64 camelized = cssProp.charAt(0) === '-'
65 ? parts[ 0 ].charAt( 0 ).toUpperCase() + parts[ 0 ].substring( 1 )
68 for( i = 1; i < l; ++i ){
69 camelized += parts[ i ].charAt( 0 ).toUpperCase() + parts[ i ].substring( 1 );
71 return me._DICTIONARY_CAMELIZE[ cssProp ] = camelized;
74 /* fontSize -> font-size */
77 uncamelize: function( str ){
78 return str.split( ' ' ).join( '' ).replace( X.Dom.Style.REG_LARGE, '-$&' ).toLowerCase();
81 CHAR_CODE_A : 'A'.charCodeAt( 0 ),
83 _DICTIONARY_UNCAMELIZE : {},
85 uncamelize : function( str ){
89 uncamelized, l, chr, code;
90 str = str.split( ' ' ).join( '' );
91 if( uncamelized = me._DICTIONARY_UNCAMELIZE[ str ] ) return 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;
98 return me._DICTIONARY_UNCAMELIZE[ str ] = uncamelized.toLowerCase();
102 * CSS における display, position, float プロパティの相互関係
103 * http://d.hatena.ne.jp/elm200/20080201/1201874740
105 * CSS21:9.7 Relationships between ’display’, ’position’, and ’float’
106 * http://www.w3.org/TR/CSS21/visuren.html#dis-pos-flo
108 * display:none? -yes-> 非表示
110 * position:absolute? -yes-> float:none,display:block;
112 * float:none? -no-> display:block;
117 display position float
118 block static|relative none
119 block static|relative right|left
121 inline static|relative none
128 objToCssText : function( obj ){
131 uncamelize = me.uncamelize,
132 VENDER_PREFIX = me.VENDER_PREFIX,
133 FIX_PROP = me.SPECIAL_FIX_PROP,
134 SPECIAL_FIX = me.SPECIAL_FIX,
137 name = uncamelize( p );
138 if( FIX_PROP[ name ] ){
141 css[ css.length ] = [ VENDER_PREFIX[ name ] || name, obj[ p ] ].join( ':' );
144 sp && ( css[ css.length ] = SPECIAL_FIX( obj ) );
145 return css.join( ';' );
149 _FONT_SIZE_RATIO : null,
151 // https://developer.mozilla.org/en-US/docs/Web/CSS/transform
152 // Firefox 3.5, ie9, Opera 10.5, Safari 3.1, Chrome
153 // 3D support Firefox 10, ie10, Safari 4.0, Chrome 12.0
154 // transform : void 0,
156 // https://developer.mozilla.org/ja/docs/Web/Guide/CSS/Using_CSS_transitions
157 // Chrome 1.0, Firefox 4.0, ie10, Opera 10.5, Safari 3.2
158 // Android 2.1, Firefox Android 4.0, Opera Mobile 10, Safari Mobile 3.2
159 // transition : void 0
161 // ブラウザ毎の getComputedStyle の戻り値 http://d.hatena.ne.jp/uupaa/20080928/1222543331
183 SLATEGRAY : 0x708090,
185 GAINSBORO : 0xDCDCDC,
186 MIDNIGHTBLUE : 0x191970,
187 SLATEBLUE : 0x6A5ACD,
188 MEDIUMBLUE : 0x0000CD,
189 ROYALBLUE : 0x4169E1,
190 DODGERBLUE : 0x1E90FF,
192 STEELBLUE : 0x4682B4,
193 LIGHTBLUE : 0xADD8E6,
194 PALETURQUOISE : 0xAFEEEE,
195 TURQUOISE : 0x40E0D0,
196 LIGHTCYAN : 0xE0FFFF,
197 AQUAMARINE : 0x7FFFD4,
198 DARKGREEN : 0x006400,
200 LIGHTGREEN : 0x90EE90,
201 CHARTREUSE : 0x7FFF00,
202 GREENYELLOW : 0xADFF2F,
203 LIMEGREEN : 0x32CD32,
204 YELLOWGREEN : 0x9ACD32,
205 OLIVEDRAB : 0x6B8E23,
206 DARKKHAKI : 0xBCB76B,
207 PALEGOLDENROD : 0xEEE8AA,
208 LIGHTYELLOW : 0xFFFFE0,
210 GOLDENROD : 0xDAA520,
211 DARKGOLDENROD : 0xB8860B,
212 ROSYBROWN : 0xBC8F8F,
213 INDIANRED : 0xCD5C5C,
214 SADDLEBROWN : 0x8B4513,
217 BURLYWOOD : 0xDEB887,
220 SANDYBROWN : 0xF4A460,
222 CHOCOLATE : 0xD2691E,
223 FIREBRICK : 0xB22222,
232 PALEVIOLETRED : 0xDB7093,
236 DARKVIOLET : 0x9400D3,
237 BLUEVIOLET : 0x8A2BE2,
238 MEDIUMPURPLE : 0x9370DB,
241 MISTYROSE : 0xFFE4E1,
243 LEMONCHIFFON : 0xFFFACD
246 PARAMS : ( function(){
248 register( ret.percent = {},
249 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom,paddingLeft,paddingRight,paddingTop,fontSize,textIndent'
251 register( ret.offset = {},
252 'height,width,bottom,left,right,top'
254 register( ret.size = {},
255 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth,letterSpacing,wordSpacing'
257 register( ret.color = {},
258 'backgroundColor,borderBottomColor,borderLeftColor,borderRightColor,borderTopColor,color'
260 register( ret.region = {},
261 'margin,padding,borderWidth,borderColor'
263 register( ret.special = {},
264 'clip,backgroundPosition,backgroundPositionX,backgroundPositionY,opacity,lineHeight,zIndex'
266 register( ret.unit = {}, 'px,cm,mm,in,pt,pc,em,%' );
268 register( ret.margin = {}, 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom' );
269 register( ret.padding = {}, 'paddingBottom,paddingLeft,paddingRight,paddingTop' );
270 register( ret.borderWidth = {}, 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth' );
271 register( ret.borderColor = {}, 'borderBottomColor,borderLeftColor,borderRightColor,borderTopColor' );
273 function register( obj, params ){
274 params = params.split( ',' );
275 for( var i = params.length; i; ) obj[ params[ --i ] ] = true;
280 _CLIP_SEPARATOR : X.UA.IE && X.UA.IE < 8 ? ' ' : ',',
285 Property : X.Class.create(
289 Constructor : function( name, value, unit, xnode ){
299 equal : function( prop ){
300 if( this.unit === prop.unit ){
301 return this.value === prop.value;
303 return Math.abs( this.toPx() - prop.toPx() ) < 1;
305 convert: function( prop ){
306 var u = prop.unit, v;
307 if( this.unit === u ) return;
308 this.value = v = this.toPx();
311 // bgpX, bgpY の場合 X.Dom.Image.getActualDimension( backgroundImage url を使用 )
315 v / this.xnode._getCharSize() :
316 v / ( X.Dom.Style._UNIT_RATIO[ u ] || 1 );
319 setValue: function( v ){
322 getValue: function(){
325 getOffset: function( prop ){
326 return prop.value - this.value;
331 getValueText: function(){
332 return this.value === 0 ? '0' : this.value + this.unit;
335 var v = this.value, u = this.unit;
339 ( u === 'em' || ( u === '' && this.name === 'lineHeight' ) ) ?
340 v * this.xnode._getCharSize() :
342 v / ( X.Dom.Style._UNIT_RATIO[ u ] || 1 );
345 var p = X.Dom.Style.PARAMS,
349 z = u !== '' ? true : v === 0;
350 if( p.percent[ n ] === true ) return z;
351 if( p.offset[ n ] === true ) return z;
352 if( p.size[ n ] === true ) return z && u !== '%';
353 if( p.special[ n ] === true ){
354 if( n === 'lineHeight' ) return true;
355 if( n === 'opacity' ) return 0 <= v && v <= 1 && u === '';
356 if( n === 'zIndex' ) return u === '';
364 * backgroundPosition, clip
366 PropertyGroup : X.Class.create(
370 Constructor : function( name ){
373 for( var i = 1, l = arguments.length; i<l; ++i ){
374 this.props[ this.props.length ] = arguments[ i ];
378 equal : function( prop ){
379 var ps = this.props, i = ps.length;
382 if( ps[ i ].equal( prop[ i ] ) === false ) return false;
386 convert : function( prop ){
387 var ps = this.props, i = ps.length;
390 ps[ i ].convert( prop[ i ] );
393 setValue : function( ary ){
394 var ps = this.props, i = 0, l = ps.length;
396 ps[ i ].setValue( ary[ i ] );
399 getValue : function(){
400 var ret = [], ps = this.props, i = 0, l = ps.length;
402 ret[ ret.length ] = ps[ i ].getValue();
406 getOffset : function( prop ){
413 ret[ ret.length ] = ps[ i ].getOffset( _ps[ i ] );
417 getUnit : function(){
418 var ret = [], ps = this.props, i = 0, l = ps.length;
420 ret[ ret.length ] = ps[ i ].getUnit();
424 getValueText : function(){
425 var ret = [], ps = this.props, i = 0, l = ps.length;
427 ret[ ret.length ] = ps[ i ].getValueText();
429 if( this.name === 'clip' ){
430 return 'rect(' + ret.join( X.Dom.Style._CLIP_SEPARATOR ) + ')';
432 return ret.join( ' ' );
435 var ps = this.props, i = ps.length;
440 isValid : function( t ){
442 var ps = t.props, i = ps.length;
444 if( ps[ --i ].isValid() === false ) return false;
452 * http://css-eblog.com/ie-css-problems/rgba-pe.html
453 * ie67 では rgb() は background-color で反応しない、、、
456 ColorProperty : X.Class.create(
458 X.Class.POOL_OBJECT, {
459 Constructor : function( name, x ){
466 if( X.Type.isNumber( rgb = x ) || X.Type.isNumber( rgb = X.Dom.Style.COLOR[ x.toUpperCase() ] ) ){
467 r = ( rgb & 0xff0000 ) >> 16;
468 g = ( rgb & 0xff00 ) >> 8;
471 if( x.charAt( 0 ) === '#' ){
472 if( x.length === 7 ){
473 r = parseInt( x.charAt( 1 ) + x.charAt( 2 ), 16 );
474 g = parseInt( x.charAt( 3 ) + x.charAt( 4 ), 16 );
475 b = parseInt( x.charAt( 5 ) + x.charAt( 6 ), 16 );
477 if( x.length === 4 ){
478 r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
479 g = parseInt( x.charAt( 2 ) + x.charAt( 2 ), 16 );
480 b = parseInt( x.charAt( 3 ) + x.charAt( 3 ), 16 );
482 if( x.length === 2 ){
483 r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
484 g = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
485 b = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
488 if( x.indexOf( 'rgb(' ) === 0 ){
489 rgb = x.substr( 4 ).split( ',' );
490 r = parseFloat( rgb[ 0 ] );
491 g = parseFloat( rgb[ 1 ] );
492 b = parseFloat( rgb[ 2 ] );
493 if( x.indexOf( '%' ) !== -1 ) pct = true;
495 if( x.indexOf( 'rgba(' ) === 0 ){
496 rgb = x.substr( 5 ).split( ',' );
497 r = parseFloat( rgb[ 0 ] );
498 g = parseFloat( rgb[ 1 ] );
499 b = parseFloat( rgb[ 2 ] );
500 a = parseFloat( rgb[ 3 ] );
501 if( x.indexOf( '%' ) !== -1 ) pct = true;
521 equal : function( prop ){
522 if( this.pct === prop.pct ){
523 return this.r === prop.r && this.g === prop.g && this.b === prop.b;
525 var rgb = this._toPct(),
526 _rgb = prop._toPct(),
530 if( Math.abs( rgb[ i ] - _rgb[ i ] ) > 1 ) return false;
534 convert : function( prop ){
536 if( this.pct === u ) return;
537 x = u === true ? 100 / 255 : 2.55;
543 setValue : function( rgb ){
548 getValue : function(){
549 return [ this.r, this.g, this.b ];
551 getOffset : function( prop ){
552 return [ prop.r - this.r, prop.g - this.g, prop.b - this.b ];
554 getUnit : function(){
555 return this.pct === true ? '%' : '';
557 getValueText : function(){
558 if( this.pct === true ){
559 return [ 'rgb(', this.r, '%,', this.g, '%,', this.b, '%)' ].join( '' );
561 var round = Math.round;
563 var rgb = '00000' + ( ( round( this.r ) << 16 ) + ( round( this.g ) << 8 ) + round( this.b ) ).toString( 16 );
564 return '#' + rgb.substr( rgb.length - 6 );
567 if( this.pct === true ) return [ this.r, this.g, this.b ];
568 return [ this.r / 2.55, this.g / 2.55, this.b / 2.55 ];
570 isValid : function( t ){
571 var isFinite = window.isFinite;
572 if( !isFinite( this.r ) || !isFinite( this.g ) || !isFinite( this.b ) ) return false;
573 if( 0 > this.r || 0 > this.g || 0 > this.b ) return false;
574 if( this.pct === true ) return this.r <= 100 && this.g <= 100 && this.b <= 100;
575 return this.r <= 255 && this.g <= 255 && this.b <= 255;
580 _getProperty : function( xnode, css, unit, p ){
582 var XDomStyle = X.Dom.Style,
583 me = XDomStyle._getProperty,
584 PARAMS = XDomStyle.PARAMS,
585 PropertyGroup = XDomStyle.PropertyGroup,
586 Property = XDomStyle.Property,
587 ColorProperty = XDomStyle.ColorProperty,
590 if( PARAMS.special[ p ] === true || PARAMS.region[ p ] === true ){
593 // rect(...) クリップします。<top>, <bottom> は上端からの、 <right>, <left> は左端からのオフセットで指定します。Internet Explorer 4~7 では、カンマの代わりにスペースで区切る必要があります。
594 // position:absolute または position:fixed を適用した要素に対してのみ有効です。
595 var top = me( p + 'Top' ),
596 right = me( p + 'Right' ),
597 bottom = me( p + 'Bottom' ),
598 left = me( p + 'Left' ),
599 ret = new PropertyGroup( p, top, right, bottom, left ),
601 if( ret.isValid() === true ) return ret;
603 all = css[ p ].split( '(' )[ 1 ].split( ')' )[ 0 ].split( XDomStyle._CLIP_SEPARATOR );
607 new Property( p + 'Top', all[ 0 ], 'px', xnode ),
608 new Property( p + 'Right', all[ 1 ], 'px', xnode ),
609 new Property( p + 'Bottom', all[ 2 ], 'px', xnode ),
610 new Property( p + 'Left', all[ 3 ], 'px', xnode )
618 var props = '$1Top$2,$1Right$2,$1Bottom$2,$1Left$2'.split( '$1' ).join( name || 'border' ).split( '$2' ).join( width || 'Width' ).split( ',' ),
619 top = me( props[ 0 ] ),
620 right = me( props[ 1 ] ),
621 bottom = me( props[ 2 ] ),
622 left = me( props[ 3 ] ),
623 ret = new PropertyGroup( p, top, right, bottom, left ),
624 all, _0, _1, _2, _3, vu, v, u;
625 if( ret.isValid() === true ) return ret;
627 all = css[ p ].split( ' ' );
632 vu = XDomStyle._Util._splitValueAndUnit( _0 );
635 switch( all.length ){
637 top = new Property( props[ 0 ], v, u, xnode );
638 right = new Property( props[ 1 ], v, u, xnode );
639 bottom = new Property( props[ 2 ], v, u, xnode );
640 left = new Property( props[ 3 ], v, u, xnode );
643 top = new Property( props[ 0 ], v, u, xnode );
644 bottom = new Property( props[ 2 ], v, u, xnode );
645 vu = XDomStyle._Util._splitValueAndUnit( _1 );
648 right = new Property( props[ 1 ], v, u, xnode );
649 left = new Property( props[ 3 ], v, u, xnode );
652 top = new Property( props[ 0 ], v, u, xnode );
653 vu = XDomStyle._Util._splitValueAndUnit( _1 );
656 right = new Property( props[ 1 ], v, u, xnode );
657 left = new Property( props[ 3 ], v, u, xnode );
658 vu = XDomStyle._Util._splitValueAndUnit( _2 );
661 bottom = new Property( props[ 2 ], v, u, xnode );
664 top = new Property( props[ 0 ], v, u, xnode );
665 vu = XDomStyle._Util._splitValueAndUnit( _1 );
668 right = new Property( props[ 1 ], v, u, xnode );
669 vu = XDomStyle._Util._splitValueAndUnit( _2 );
672 bottom = new Property( props[ 2 ], v,u, xnode );
673 vu = XDomStyle._Util._splitValueAndUnit( _3 );
676 left = new Property( props[ 3 ], v, u, xnode );
679 return new PropertyGroup( p, top, right, bottom, left );
682 var props = 'borderTopColor,borderRightColor,borderBottomColor,borderLeftColor'.split( ',' ),
683 top = me( props[ 0 ] ),
684 right = me( props[ 1 ] ),
685 bottom = me( props[ 2 ] ),
686 left = me( props[ 3 ] ),
687 ret = new PropertyGroup( p, top, right, bottom, left ),
689 if( ret.isValid() === true ) return ret;
691 all = css[ p ].split( ' ' );
694 switch( all.length ){
696 top = new ColorProperty( props[ 0 ], _0 );
697 right = new ColorProperty( props[ 1 ], _0 );
698 bottom = new ColorProperty( props[ 2 ], _0 );
699 left = new ColorProperty( props[ 3 ], _0 );
702 top = new ColorProperty( props[ 0 ], _0 );
703 right = new ColorProperty( props[ 1 ], _1 );
704 bottom = new ColorProperty( props[ 2 ], _0 );
705 left = new ColorProperty( props[ 3 ], _1 );
708 top = new ColorProperty( props[ 0 ], _0 );
709 right = new ColorProperty( props[ 1 ], _1 );
710 bottom = new ColorProperty( props[ 2 ], all[ 2 ] );
711 left = new ColorProperty( props[ 3 ], _1 );
714 top = new ColorProperty( props[ 0 ], _0 );
715 right = new ColorProperty( props[ 1 ], _1 );
716 bottom = new ColorProperty( props[ 2 ], all[ 2 ] );
717 left = new ColorProperty( props[ 3 ], all[ 3 ] );
720 return new PropertyGroup( p, top, right, bottom, left );
722 case 'backgroundPosition' :
723 var x = me( p + 'X' ),
725 ret = new PropertyGroup( p, x, y ),
727 if( ret.isValid() === true ) return ret;
729 xy = css[ p ].split( ' ' );
730 x = XDomStyle._Util._splitValueAndUnit( xy[ 0 ] );
731 y = XDomStyle._Util._splitValueAndUnit( xy[ 1 ] );
735 new Property( p + 'X', x[ 0 ], x[ 1 ], xnode ),
736 new Property( p + 'Y', y[ 0 ], y[ 1 ], xnode )
739 // opacity, zindex, lineHeight
740 vu = XDomStyle._Util._splitValueAndUnit( css[ p ] );
741 return new Property( p, vu[ 0 ], vu[ 1 ], xnode );
743 var x = css[ p ], e, v, u;
745 if( PARAMS.offset[ p ] === true ){
746 return new Property( p, vu[ 0 ], vu[ 1 ], xnode );
749 if( p === 'width' ) v = e.offsetWidth;
750 if( p === 'height' ) v = e.offsetHeight;
751 if( p === 'top' ) v = e.offsetTop;
752 if( p === 'bottom' ) v = e.offsetBottom;
753 if( p === 'left' ) v = e.offsetLeft;
754 if( p === 'right' ) v = e.offsetRight;
755 u = _getUnit( x, p );
756 // alert( p + XDomStyle._Util.pxTo( v, u ) + u )
757 return new Property( p, XDomStyle._Util.pxTo( v, u ), u, xnode );
759 if( p === 'fontSize' && ( v = XDomStyle._FONT_SIZE_RATIO[ x ] ) ){ // xx-small 等
760 return new Property( p, v, 'px', xnode );
762 if( PARAMS.offset[ p ] || PARAMS.percent[ p ] || PARAMS.size[ p ] ){
763 vu = XDomStyle._Util._splitValueAndUnit( x );
764 return new Property( p, vu[ 0 ], vu[ 1 ], xnode );
767 if( PARAMS.color[ p ] ) return new ColorProperty( p, x );
772 getValue: function( x ){
773 return X.Type.isString( x ) ? parseInt( x ) :
774 X.Type.isNumber( x ) ? x : 0;
776 getUnit: function( x, p ){
779 var REG_UINIT = /.*\d(\w{1,2})?/,
784 if( X.Type.isString( x ) === true ){
785 u = x.replace( REG_UINIT, $1 );
786 if( p === 'lineHeight' ) return u;
787 if( PARAMS.unit[ u ] !== true ) return 'px';
792 _splitValueAndUnit : function( v ){
794 if( X.Type.isNumber( v ) ) return [ v || 0, '' ];
795 if( isNaN( num = parseInt( v ) ) ) return [ 0, '' ];
797 i = v.indexOf( _num ) + _num.length;
799 return [ num, X.Dom.Style.UNIT[ u ] ? u : 'px' ];
804 X.Dom.Style._GET_VALUE_WITH_UNIT = {
805 borderWidth : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH,
806 //borderStyle : X.Dom.Style.Type.QUARTET,
807 borderRadius : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH,
808 margin : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
809 padding : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
810 clip : X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
812 backgroundColor : X.Dom.Style.Type.COLOR,
813 backgroundPosition : X.Dom.Style.Type.COMBI,
817 fontSize : X.Dom.Style.Type.LENGTH,
818 lineHeight : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT | X.Dom.Style.Type.NUMERICAL,
819 textIndent : X.Dom.Style.Type.LENGTH,
820 letterSpacing : X.Dom.Style.Type.LENGTH,
821 wordSpacing : X.Dom.Style.Type.LENGTH,
823 textShadowColor : X.Dom.Style.Type.COLOR,
824 textShadowOffsetX : X.Dom.Style.Type.LENGTH,
825 textShadowOffsetY : X.Dom.Style.Type.LENGTH,
826 textShadowBlur : X.Dom.Style.Type.LENGTH, */
828 width : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
829 height : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
831 left : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
832 top : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
833 bottom : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
834 right : X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT,
837 borderSpacing : X.Dom.Style.Type.LENGTH
841 X.Dom.Style.SPECIAL_FIX =
843 X.UA.IE && X.UA.IE < 9 ?
845 var test = X.Dom.Style.SPECIAL_FIX_PROP,
846 filters = [], p, id, v;
848 if( !( id = test[ p ] ) ) continue;
851 case 1 : //'filter' :
852 filters[ filters.length ] = v;
854 case 2 : //'opacity' :
855 filters[ filters.length ] = 'aplha(opacity=' + v +')';
857 case 3 : //'boxShadow' :
858 // box-shadow: 10px 10px 10px 10px rgba(0,0,0,0.4) inset;
859 // スペース区切りで、水平方向の距離 垂直方向の距離 ぼかし距離 広がり距離 影の色 insetキーワードを指定する。 ぼかし距離 広がり距離 影の色 insetキーワードは省略可
860 // shadow(color=#cccccc, strength=10, direction=135);
861 parseValue( 'boxShadow', v, 'px' );
862 dir = Math.atan2( ary[1], ary[0] ) * 180 / Math.PI + 90;
863 dir += dir < 0 ? 360 : 0;
865 case 4 : //'textShadow' :
866 //text-shadow: 5px 5px 2px blue; 水平方向の距離 垂直方向の距離 影のぼかし半径 影の色 none
867 //glow(Color=yellow,Strength=10);
868 //どうやらCSSのbackgroundプロパティと同時に使えないようです。
870 case 5 : //'backgroundImage' :
874 if( filters ) return filters.join( ' ' );
876 // IE9 textShadow に filter を使用
877 X.UA.IE && 9 <= X.UA.IE && X.UA.IE < 10 ?
879 var test = X.Dom.Style.SPECIAL_FIX_PROP,
880 filters = [], p, id, v;
882 if( !( id = test[ p ] ) ) continue;
885 case 1 : //'filter' :
886 filters[ filters.length ] = v;
890 if( filters ) return filters.join( ' ' );
893 var test = X.Dom.Style.SPECIAL_FIX_PROP,
896 if( !( id = test[ p ] ) ) continue;
899 case 1 : //'backgroundPositionX' :
902 case 2 : //'backgroundPositionY' :
905 case 3 : //'backgroundPositionX' :
908 case 4 : //'backgroundPositionX' :
911 case 5 : //'backgroundPositionX' :
914 case 6 : //'backgroundPositionX' :
919 if( bgpX || bgpY ) ret[ ret.length ] = 'background-position:';
920 if( clipT || clipB || clipL || clipR ){
921 ret[ ret.length ] = 'clip:rect(';
923 return ret.join( ';' );
931 // unitID, name 単位指定のプロパティ取得 geter
933 // name, value setter
935 X.Dom.Node.prototype.css = function( nameOrObj /* orUnitID, valuOrUnitOrName */ ){
936 var XDomStyle = X.Dom.Style,
939 p, valOrUnit, name, v, camelize, unit;
940 if( this._xnodeType !== 1 ) return this;
942 if( X.Type.isObject( nameOrObj ) ){
943 if( !css ) css = this._css = {};
944 camelize = XDomStyle.camelize;
945 for( p in nameOrObj ){
946 css[ camelize( p ) ] = nameOrObj[ p ];
948 this._dirty |= X.Dom.Dirty.CSS;
949 this.parent && this._reserveUpdate();
950 delete this._cssText;
953 if( 1 < args.length ){
954 if( !( unit = XDomStyle.UNIT[ nameOrObj ] ) ){
955 // setter name, value
956 if( !css ) css = this._css = {};
957 name = XDomStyle.camelize( nameOrObj );
959 if( css[ name ] === v ) return this;
965 delete this._cssText;
966 this._dirty |= X.Dom.Dirty.CSS;
967 // parent でなく this._root!
968 this.parent && this._reserveUpdate();
972 // unit 付の値取得は fontSize と 画像サイズが確定していないと正確に取れない。内部のみにする?
974 if( !XDomStyle._GET_VALUE_WITH_UNIT[ name = XDomStyle.camelize( args[ 1 ] ) ] ) return null;
975 p = XDomStyle._getProperty( this, css, unit, name );
982 // 集計 border, padding, margin, backgroundPosition, clip
983 // border で正確なデータを返せない時は、null を返す
984 return css[ XDomStyle.camelize( nameOrObj ) ];
987 X.Dom.Node.prototype.cssText = function( v ){
988 var obj, i, l, attr, name;
989 if( X.Type.isString( v ) ){
993 for( i = 0, l = v.length; i < l; ++i ){
994 attr = v[ i ].split( ':' );
995 ( name = attr[ 0 ] ) && ( obj[ name ] = attr[ 1 ] || true );
997 return this.css( obj );
999 return this._cssText;
1003 * ここでは HTMLElement のチャックは行わない!
1005 X.Dom.Node.prototype._getCharSize =
1006 window.getComputedStyle ?
1008 return parseInt( getComputedStyle( this._rawNode, null ).fontSize );
1010 document.defaultView && document.defaultView.getComputedStyle ?
1012 return parseInt( document.defaultView.getComputedStyle( this._rawNode, null ).fontSize );
1014 X.UA.IE && 5 <= X.UA.IE ?
1016 var font = this._rawNode.currentStyle.fontSize,
1017 vu = X.Dom.Style._Util._splitValueAndUnit( font ),
1024 // body まで辿ってしまった場合は?
1025 return this.parent._getCharSize() * v;
1027 // body まで辿ってしまった場合は?
1028 return this.parent._getCharSize() * v / 100;
1031 ( X.Dom.Style._FONT_SIZE_RATIO[ font ] || 0 ) :
1032 v / ( X.Dom.Style._UNIT_RATIO[ u ] || 1 );
1036 document.getElementById ?
1038 var elm = document.createElement( 'span' ),
1040 elm.style.cssText = 'display:block;position:absolute;top:0;left:0;visivility:hidden;line-height:1;height:1em;';
1041 elm.innerHTML = 'X';
1042 this._rawNode.appendChild( elm );
1043 v = elm.offsetHeight;
1044 this._rawNode.removeChild( elm );
1049 var elm = this._rawNode, v;
1050 elm.insertAdjacentHTML( 'BeforeEnd', '<span style="visivility:hidden;line-height:1;">X</span>' );
1051 elm = elm.children[ elm.children.length - 1 ];
1052 v = elm.offsetHeight;
1060 X.Dom.listenOnce( X.Dom.Event.DOM_PRE_INIT, function(){
1061 var testStyle = X.Dom._root;
1063 X.Dom.Style.VENDER_PREFIX = (function(){
1065 vendors = 'webkit,Webkit,Moz,moz,ms,Ms,O,o,khtml,Khtml'.split( ',' ),
1067 'opacity,boxSizing,' +
1068 'transform,transformOrigin,perspective,' +
1069 'transisiton,transitionDelay,transitionProperty,transitionDuration,transitionTimingFunction,' +
1070 'userSelect,touchAction,touchCallout,contentZooming,userDrag,tapHighlightColor'.split( ',' ),
1071 vendor, i, search, prop;
1073 vendors.unshift( '' );
1075 function findVenderPrefix( prop ){
1076 var v, i = vendors.length;
1080 if( testStyle[ v + prop ] !== undefined ){
1087 for( i = searches.length; i; ){
1088 search = searches[ --i ];
1089 prop = findVenderPrefix( search );
1090 if( search === 'transform' ) ret.transVender = vendor;
1091 if( prop ) ret[ search ] = prop;
1096 X.Dom.Style.SPECIAL_FIX_PROP =
1098 X.UA.IE && X.UA.IE < 9 ?
1101 opacity : 2//, uinode ChromeNode で行う
1104 //backgroundImage : 5
1107 X.UA.IE && 9 <= X.UA.IE && X.UA.IE < 10 ?
1113 backgroundPositionX : testStyle.backgroundPositionX === undefined ? 3 : 0,
1114 backgroundPosiitonY : testStyle.backgroundPositionX === undefined ? 3 : 0,
1115 clipTop : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 3 : 0,
1116 clipBottom : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 4 : 0,
1117 clipLeft : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 5 : 0,
1118 clipRight : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 6 : 0
1122 X.Dom.listenOnce( X.Dom.Event.DOM_INIT, function(){
1123 var xnode = Node._systemNode,
1124 output = X.Dom.Style._UNIT_RATIO = {},
1125 list = 'em,cm,mm,in,pt,pc'.split( ',' ),
1128 for( i = list.length; i; ){
1130 output[ unit ] = xnode.css( 'width', 100 + unit ).width() / 100;
1133 output = X.Dom.Style._FONT_SIZE_RATIO = {},
1134 list = 'xx-large,x-large,large,larger,medium,small,smaller,x-small,xx-small'.split( ',' );
1135 base = xnode.css( 'lineHeight', 1 ).text( 'X' ).height();
1137 for( i = list.length; i; ){
1139 output[ size ] = xnode.css( 'fontSize', size ).height() / base;
1142 xnode.empty().cssText( '' );