4 * style 値の変更は、enterFrame 後にまとめて適用
5 * width(), height(), x(), y() 1em の取得時にも適用
6 * css3 の ie用 fix は X.UI レベルで行う
43 /* font-size -> fontSize */
44 X_Node_CSS__DICTIONARY_CAMELIZE = {},
46 X_Node_CSS_camelize = function( cssProp ){
47 var parts, l, i, camelized;
49 if( camelized = X_Node_CSS__DICTIONARY_CAMELIZE[ cssProp ] ) return camelized;
50 parts = cssProp.split( ' ' ).join( '' ).split( '-' );
52 if( l === 1 ) return parts[ 0 ];
54 camelized = cssProp.charAt(0) === '-'
55 ? parts[ 0 ].charAt( 0 ).toUpperCase() + parts[ 0 ].substring( 1 )
58 for( i = 1; i < l; ++i ){
59 camelized += parts[ i ].charAt( 0 ).toUpperCase() + parts[ i ].substring( 1 );
61 return X_Node_CSS__DICTIONARY_CAMELIZE[ cssProp ] = camelized;
64 /* fontSize -> font-size */
65 X_Node_CSS_CHAR_CODE_A = 'A'.charCodeAt( 0 ),
67 X_Node_CSS__DICTIONARY_UNCAMELIZE = {},
69 X_Node_CSS_uncamelize = function( str ){
70 var A = X_Node_CSS_CHAR_CODE_A,
72 uncamelized, l, chr, code, i;
73 str = str.split( ' ' ).join( '' );
74 if( uncamelized = X_Node_CSS__DICTIONARY_UNCAMELIZE[ str ] ) return uncamelized;
76 for( i = 0, l = str.length; i < l; ++i ){
77 chr = str.charAt( i );
78 code = chr.charCodeAt( 0 );
79 uncamelized += ( A <= code && code <= Z ) ? '-' + chr : chr;
81 return X_Node_CSS__DICTIONARY_UNCAMELIZE[ str ] = uncamelized.toLowerCase();
85 * CSS における display, position, float プロパティの相互関係
86 * http://d.hatena.ne.jp/elm200/20080201/1201874740
88 * CSS21:9.7 Relationships between ’display’, ’position’, and ’float’
89 * http://www.w3.org/TR/CSS21/visuren.html#dis-pos-flo
91 * display:none? -yes-> 非表示
93 * position:absolute? -yes-> float:none,display:block;
95 * float:none? -no-> display:block;
100 display position float
101 block static|relative none
102 block static|relative right|left
104 inline static|relative none
111 X_Node_CSS_VENDER_PREFIX = {},
113 X_Node_CSS_objToCssText = function( obj ){
115 uncamelize = X_Node_CSS_uncamelize,
116 VENDER_PREFIX = X_Node_CSS_VENDER_PREFIX,
117 FIX_PROP = X_Node_CSS_SPECIAL_FIX_PROP,
118 SPECIAL_FIX = X_Node_CSS_SPECIAL_FIX,
121 if( !obj ) return ''; // Opera7.5 未満?
123 // TODO Object が拡張されていると error...
124 name = uncamelize( VENDER_PREFIX[ p ] || p );
125 if( FIX_PROP[ name ] ){
128 css[ ++n ] = [ name, obj[ p ] ].join( ':' );
131 sp && ( css[ ++n ] = 'filter:' + SPECIAL_FIX( obj ) );
132 return css.join( ';' );
135 X_Node_CSS_IE_FILTER_FIX =
136 X_UA.IE && X_UA.IE < 9 && !X_UA.MacIE ?
141 9 <= X_UA.IE && X_UA.IE < 10 ? // == 9
145 X_Node_CSS__UNIT_RATIO = {},
146 X_Node_CSS__FONT_SIZE_RATIO = {},
148 // https://developer.mozilla.org/en-US/docs/Web/CSS/transform
149 // Firefox 3.5, ie9, Opera 10.5, Safari 3.1, Chrome
150 // 3D support Firefox 10, ie10, Safari 4.0, Chrome 12.0
151 // transform : void 0,
153 // https://developer.mozilla.org/ja/docs/Web/Guide/CSS/Using_CSS_transitions
154 // Chrome 1.0, Firefox 4.0, ie10, Opera 10.5, Safari 3.2
155 // Android 2.1, Firefox Android 4.0, Opera Mobile 10, Safari Mobile 3.2
156 // transition : void 0
158 // ブラウザ毎の getComputedStyle の戻り値 http://d.hatena.ne.jp/uupaa/20080928/1222543331
180 SLATEGRAY : 0x708090,
182 GAINSBORO : 0xDCDCDC,
183 MIDNIGHTBLUE : 0x191970,
184 SLATEBLUE : 0x6A5ACD,
185 MEDIUMBLUE : 0x0000CD,
186 ROYALBLUE : 0x4169E1,
187 DODGERBLUE : 0x1E90FF,
189 STEELBLUE : 0x4682B4,
190 LIGHTBLUE : 0xADD8E6,
191 PALETURQUOISE : 0xAFEEEE,
192 TURQUOISE : 0x40E0D0,
193 LIGHTCYAN : 0xE0FFFF,
194 AQUAMARINE : 0x7FFFD4,
195 DARKGREEN : 0x006400,
197 LIGHTGREEN : 0x90EE90,
198 CHARTREUSE : 0x7FFF00,
199 GREENYELLOW : 0xADFF2F,
200 LIMEGREEN : 0x32CD32,
201 YELLOWGREEN : 0x9ACD32,
202 OLIVEDRAB : 0x6B8E23,
203 DARKKHAKI : 0xBCB76B,
204 PALEGOLDENROD : 0xEEE8AA,
205 LIGHTYELLOW : 0xFFFFE0,
207 GOLDENROD : 0xDAA520,
208 DARKGOLDENROD : 0xB8860B,
209 ROSYBROWN : 0xBC8F8F,
210 INDIANRED : 0xCD5C5C,
211 SADDLEBROWN : 0x8B4513,
214 BURLYWOOD : 0xDEB887,
217 SANDYBROWN : 0xF4A460,
219 CHOCOLATE : 0xD2691E,
220 FIREBRICK : 0xB22222,
229 PALEVIOLETRED : 0xDB7093,
233 DARKVIOLET : 0x9400D3,
234 BLUEVIOLET : 0x8A2BE2,
235 MEDIUMPURPLE : 0x9370DB,
238 MISTYROSE : 0xFFE4E1,
240 LEMONCHIFFON : 0xFFFACD
243 X_Node_CSS_parseColor = function( x ){
246 if( X.Type.isNumber( x ) ){
247 return ( 0x0 <= x && x <= 0xFFFFFF ) ? x : undefined;
249 if( !X.Type.isString( x ) ) return;
251 if( X.Type.isNumber( rgb = X_Node_CSS_COLOR[ x.toUpperCase() ] ) && 0x0 <= rgb && rgb <= 0xFFFFFF ){
254 if( x.charAt( 0 ) === '#' ){
257 r = parseInt( x.substr( 1, 2 ), 16 );
258 g = parseInt( x.substr( 3, 2 ), 16 );
259 b = parseInt( x.substr( 5, 2 ), 16 );
262 r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
263 g = parseInt( x.charAt( 2 ) + x.charAt( 2 ), 16 );
264 b = parseInt( x.charAt( 3 ) + x.charAt( 3 ), 16 );
267 r = g = b = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
273 if( x.indexOf( 'rgb(' ) === 0 ){
274 rgb = x.substr( 4 ).split( ',' );
275 r = parseFloat( rgb[ 0 ] );
276 g = parseFloat( rgb[ 1 ] );
277 b = parseFloat( rgb[ 2 ] );
278 if( x.indexOf( '%' ) !== -1 ){
284 if( x.indexOf( 'rgba(' ) === 0 ){
285 rgb = x.substr( 5 ).split( ',' );
286 r = parseFloat( rgb[ 0 ] );
287 g = parseFloat( rgb[ 1 ] );
288 b = parseFloat( rgb[ 2 ] );
289 //a = parseFloat( rgb[ 3 ] );
290 if( x.indexOf( '%' ) !== -1 ){
298 return isFinite( r + b + g ) ? ( r << 16 ) + ( g << 8 ) + b : undefined;
301 X_Node_CSS_PARAMS = ( function(){
303 register( ret.percent = {},
304 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom,paddingLeft,paddingRight,paddingTop,fontSize,textIndent'
306 register( ret.offset = {},
307 'height,width,bottom,left,right,top'
309 register( ret.size = {},
310 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth,letterSpacing,wordSpacing'
312 register( ret.color = {},
313 'backgroundColor,borderBottomColor,borderLeftColor,borderRightColor,borderTopColor,color'
315 register( ret.region = {},
316 'margin,padding,borderWidth,borderColor'
318 register( ret.special = {},
319 'clip,backgroundPosition,backgroundPositionX,backgroundPositionY,opacity,lineHeight,zIndex'
321 register( ret.unit = {}, 'px,cm,mm,in,pt,pc,em,%' );
323 register( ret.margin = {}, 'marginBottom,marginLeft,marginRight,marginTop,paddingBottom' );
324 register( ret.padding = {}, 'paddingBottom,paddingLeft,paddingRight,paddingTop' );
325 register( ret.borderWidth = {}, 'borderBottomWidth,borderLeftWidth,borderRightWidth,borderTopWidth' );
326 register( ret.borderColor = {}, 'borderBottomColor,borderLeftColor,borderRightColor,borderTopColor' );
328 function register( obj, params ){
329 params = params.split( ',' );
330 for( var i = params.length; i; ) obj[ params[ --i ] ] = true;
335 X_Node_CSS__CLIP_SEPARATOR = X_UA.IE && X_UA.IE < 8 ? ' ' : ',',
340 X_Node_CSS_Property = X.Class.create(
344 Constructor : function( name, value, unit, xnode ){
354 equal : function( prop ){
355 if( this.unit === prop.unit ){
356 return this.value === prop.value;
358 return Math.abs( this.toPx() - prop.toPx() ) < 1;
360 convert: function( prop ){
361 var u = prop.unit, v;
362 if( this.unit === u ) return;
363 this.value = v = this.toPx();
366 // bgpX, bgpY の場合 X.Util.Image.getActualDimension( backgroundImage url を使用 )
370 v / this.xnode._getCharSize() :
371 v / ( X_Node_CSS__UNIT_RATIO[ u ] || 1 );
374 setValue: function( v ){
377 getValue: function(){
380 getOffset: function( prop ){
381 return prop.value - this.value;
386 getValueText: function(){
387 return this.value === 0 ? '0' : this.value + this.unit;
390 var v = this.value, u = this.unit;
394 ( u === 'em' || ( u === '' && this.name === 'lineHeight' ) ) ?
395 v * this.xnode._getCharSize() :
397 v / ( X_Node_CSS__UNIT_RATIO[ u ] || 1 );
400 var p = X_Node_CSS_PARAMS,
404 z = u !== '' ? true : v === 0;
405 if( p.percent[ n ] === true ) return z;
406 if( p.offset[ n ] === true ) return z;
407 if( p.size[ n ] === true ) return z && u !== '%';
408 if( p.special[ n ] === true ){
409 if( n === 'lineHeight' ) return true;
410 if( n === 'opacity' ) return 0 <= v && v <= 1 && u === '';
411 if( n === 'zIndex' ) return u === '';
419 * backgroundPosition, clip
421 X_Node_CSS_PropertyGroup = X.Class.create(
425 Constructor : function( name ){
428 for( var i = 1, l = arguments.length; i<l; ++i ){
429 this.props[ this.props.length ] = arguments[ i ];
433 equal : function( prop ){
434 var ps = this.props, i = ps.length;
437 if( ps[ i ].equal( prop[ i ] ) === false ) return false;
441 convert : function( prop ){
442 var ps = this.props, i = ps.length;
445 ps[ i ].convert( prop[ i ] );
448 setValue : function( ary ){
449 var ps = this.props, i = 0, l = ps.length;
451 ps[ i ].setValue( ary[ i ] );
454 getValue : function(){
455 var ret = [], ps = this.props, i = 0, l = ps.length;
457 ret[ ret.length ] = ps[ i ].getValue();
461 getOffset : function( prop ){
468 ret[ ret.length ] = ps[ i ].getOffset( _ps[ i ] );
472 getUnit : function(){
473 var ret = [], ps = this.props, i = 0, l = ps.length;
475 ret[ ret.length ] = ps[ i ].getUnit();
479 getValueText : function(){
480 var ret = [], ps = this.props, i = 0, l = ps.length;
482 ret[ ret.length ] = ps[ i ].getValueText();
484 if( this.name === 'clip' ){
485 return 'rect(' + ret.join( X_Node_CSS__CLIP_SEPARATOR ) + ')';
487 return ret.join( ' ' );
490 var ps = this.props, i = ps.length;
495 isValid : function( t ){
497 var ps = t.props, i = ps.length;
499 if( ps[ --i ].isValid() === false ) return false;
507 * http://css-eblog.com/ie-css-problems/rgba-pe.html
508 * ie67 では rgb() は background-color で反応しない、、、
511 X_Node_CSS_ColorProperty = X.Class.create(
513 X.Class.POOL_OBJECT, {
514 Constructor : function( name, x ){
521 if( X.Type.isNumber( rgb = x ) || X.Type.isNumber( rgb = X_Node_CSS_COLOR[ x.toUpperCase() ] ) ){
522 r = ( rgb & 0xff0000 ) >> 16;
523 g = ( rgb & 0xff00 ) >> 8;
526 if( x.charAt( 0 ) === '#' ){
527 if( x.length === 7 ){
528 r = parseInt( x.charAt( 1 ) + x.charAt( 2 ), 16 );
529 g = parseInt( x.charAt( 3 ) + x.charAt( 4 ), 16 );
530 b = parseInt( x.charAt( 5 ) + x.charAt( 6 ), 16 );
532 if( x.length === 4 ){
533 r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
534 g = parseInt( x.charAt( 2 ) + x.charAt( 2 ), 16 );
535 b = parseInt( x.charAt( 3 ) + x.charAt( 3 ), 16 );
537 if( x.length === 2 ){
538 r = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
539 g = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
540 b = parseInt( x.charAt( 1 ) + x.charAt( 1 ), 16 );
543 if( x.indexOf( 'rgb(' ) === 0 ){
544 rgb = x.substr( 4 ).split( ',' );
545 r = parseFloat( rgb[ 0 ] );
546 g = parseFloat( rgb[ 1 ] );
547 b = parseFloat( rgb[ 2 ] );
548 if( x.indexOf( '%' ) !== -1 ) pct = true;
550 if( x.indexOf( 'rgba(' ) === 0 ){
551 rgb = x.substr( 5 ).split( ',' );
552 r = parseFloat( rgb[ 0 ] );
553 g = parseFloat( rgb[ 1 ] );
554 b = parseFloat( rgb[ 2 ] );
555 a = parseFloat( rgb[ 3 ] );
556 if( x.indexOf( '%' ) !== -1 ) pct = true;
576 equal : function( prop ){
577 if( this.pct === prop.pct ){
578 return this.r === prop.r && this.g === prop.g && this.b === prop.b;
580 var rgb = this._toPct(),
581 _rgb = prop._toPct(),
585 if( Math.abs( rgb[ i ] - _rgb[ i ] ) > 1 ) return false;
589 convert : function( prop ){
591 if( this.pct === u ) return;
592 x = u === true ? 100 / 255 : 2.55;
598 setValue : function( rgb ){
603 getValue : function(){
604 return [ this.r, this.g, this.b ];
606 getOffset : function( prop ){
607 return [ prop.r - this.r, prop.g - this.g, prop.b - this.b ];
609 getUnit : function(){
610 return this.pct === true ? '%' : '';
612 getValueText : function(){
613 if( this.pct === true ){
614 return [ 'rgb(', this.r, '%,', this.g, '%,', this.b, '%)' ].join( '' );
616 var round = Math.round;
618 var rgb = '00000' + ( ( round( this.r ) << 16 ) + ( round( this.g ) << 8 ) + round( this.b ) ).toString( 16 );
619 return '#' + rgb.substr( rgb.length - 6 );
622 if( this.pct === true ) return [ this.r, this.g, this.b ];
623 return [ this.r / 2.55, this.g / 2.55, this.b / 2.55 ];
625 isValid : function( t ){
626 var isFinite = window.isFinite;
627 if( !isFinite( this.r ) || !isFinite( this.g ) || !isFinite( this.b ) ) return false;
628 if( 0 > this.r || 0 > this.g || 0 > this.b ) return false;
629 if( this.pct === true ) return this.r <= 100 && this.g <= 100 && this.b <= 100;
630 return this.r <= 255 && this.g <= 255 && this.b <= 255;
635 function X_Node_CSS__getProperty( xnode, css, unit, p ){
637 var me = X_Node_CSS__getProperty,
638 PARAMS = X_Node_CSS_PARAMS,
639 PropertyGroup = X_Node_CSS_PropertyGroup,
640 Property = X_Node_CSS_Property,
641 ColorProperty = X_Node_CSS_ColorProperty,
644 if( PARAMS.special[ p ] === true || PARAMS.region[ p ] === true ){
647 // rect(...) クリップします。<top>, <bottom> は上端からの、 <right>, <left> は左端からのオフセットで指定します。Internet Explorer 4~7 では、カンマの代わりにスペースで区切る必要があります。
648 // position:absolute または position:fixed を適用した要素に対してのみ有効です。
649 var top = me( p + 'Top' ),
650 right = me( p + 'Right' ),
651 bottom = me( p + 'Bottom' ),
652 left = me( p + 'Left' ),
653 ret = new PropertyGroup( p, top, right, bottom, left ),
655 if( ret.isValid() === true ) return ret;
657 all = css[ p ].split( '(' )[ 1 ].split( ')' )[ 0 ].split( X_Node_CSS__CLIP_SEPARATOR );
661 new Property( p + 'Top', all[ 0 ], 'px', xnode ),
662 new Property( p + 'Right', all[ 1 ], 'px', xnode ),
663 new Property( p + 'Bottom', all[ 2 ], 'px', xnode ),
664 new Property( p + 'Left', all[ 3 ], 'px', xnode )
672 var props = '$1Top$2,$1Right$2,$1Bottom$2,$1Left$2'.split( '$1' ).join( name || 'border' ).split( '$2' ).join( width || 'Width' ).split( ',' ),
673 top = me( props[ 0 ] ),
674 right = me( props[ 1 ] ),
675 bottom = me( props[ 2 ] ),
676 left = me( props[ 3 ] ),
677 ret = new PropertyGroup( p, top, right, bottom, left ),
678 all, _0, _1, _2, _3, vu, v, u;
679 if( ret.isValid() === true ) return ret;
681 all = css[ p ].split( ' ' );
686 vu = X_Node_CSS__splitValueAndUnit( _0 );
689 switch( all.length ){
691 top = new Property( props[ 0 ], v, u, xnode );
692 right = new Property( props[ 1 ], v, u, xnode );
693 bottom = new Property( props[ 2 ], v, u, xnode );
694 left = new Property( props[ 3 ], v, u, xnode );
697 top = new Property( props[ 0 ], v, u, xnode );
698 bottom = new Property( props[ 2 ], v, u, xnode );
699 vu = X_Node_CSS__splitValueAndUnit( _1 );
702 right = new Property( props[ 1 ], v, u, xnode );
703 left = new Property( props[ 3 ], v, u, xnode );
706 top = new Property( props[ 0 ], v, u, xnode );
707 vu = X_Node_CSS__splitValueAndUnit( _1 );
710 right = new Property( props[ 1 ], v, u, xnode );
711 left = new Property( props[ 3 ], v, u, xnode );
712 vu = X_Node_CSS__splitValueAndUnit( _2 );
715 bottom = new Property( props[ 2 ], v, u, xnode );
718 top = new Property( props[ 0 ], v, u, xnode );
719 vu = X_Node_CSS__splitValueAndUnit( _1 );
722 right = new Property( props[ 1 ], v, u, xnode );
723 vu = X_Node_CSS__splitValueAndUnit( _2 );
726 bottom = new Property( props[ 2 ], v,u, xnode );
727 vu = X_Node_CSS__splitValueAndUnit( _3 );
730 left = new Property( props[ 3 ], v, u, xnode );
733 return new PropertyGroup( p, top, right, bottom, left );
736 var props = 'borderTopColor,borderRightColor,borderBottomColor,borderLeftColor'.split( ',' ),
737 top = me( props[ 0 ] ),
738 right = me( props[ 1 ] ),
739 bottom = me( props[ 2 ] ),
740 left = me( props[ 3 ] ),
741 ret = new PropertyGroup( p, top, right, bottom, left ),
743 if( ret.isValid() === true ) return ret;
745 all = css[ p ].split( ' ' );
748 switch( all.length ){
750 top = new ColorProperty( props[ 0 ], _0 );
751 right = new ColorProperty( props[ 1 ], _0 );
752 bottom = new ColorProperty( props[ 2 ], _0 );
753 left = new ColorProperty( props[ 3 ], _0 );
756 top = new ColorProperty( props[ 0 ], _0 );
757 right = new ColorProperty( props[ 1 ], _1 );
758 bottom = new ColorProperty( props[ 2 ], _0 );
759 left = new ColorProperty( props[ 3 ], _1 );
762 top = new ColorProperty( props[ 0 ], _0 );
763 right = new ColorProperty( props[ 1 ], _1 );
764 bottom = new ColorProperty( props[ 2 ], all[ 2 ] );
765 left = new ColorProperty( props[ 3 ], _1 );
768 top = new ColorProperty( props[ 0 ], _0 );
769 right = new ColorProperty( props[ 1 ], _1 );
770 bottom = new ColorProperty( props[ 2 ], all[ 2 ] );
771 left = new ColorProperty( props[ 3 ], all[ 3 ] );
774 return new PropertyGroup( p, top, right, bottom, left );
776 case 'backgroundPosition' :
777 var x = me( p + 'X' ),
779 ret = new PropertyGroup( p, x, y ),
781 if( ret.isValid() === true ) return ret;
783 xy = css[ p ].split( ' ' );
784 x = X_Node_CSS__splitValueAndUnit( xy[ 0 ] );
785 y = X_Node_CSS__splitValueAndUnit( xy[ 1 ] );
789 new Property( p + 'X', x[ 0 ], x[ 1 ], xnode ),
790 new Property( p + 'Y', y[ 0 ], y[ 1 ], xnode )
793 // opacity, zindex, lineHeight
794 vu = X_Node_CSS__splitValueAndUnit( css[ p ] );
795 return new Property( p, vu[ 0 ], vu[ 1 ], xnode );
797 var x = css[ p ], e, v, u;
799 if( PARAMS.offset[ p ] === true ){
800 return new Property( p, vu[ 0 ], vu[ 1 ], xnode );
803 if( p === 'width' ) v = e.offsetWidth;
804 if( p === 'height' ) v = e.offsetHeight;
805 if( p === 'top' ) v = e.offsetTop;
806 if( p === 'bottom' ) v = e.offsetBottom;
807 if( p === 'left' ) v = e.offsetLeft;
808 if( p === 'right' ) v = e.offsetRight;
809 u = _getUnit( x, p );
810 // alert( p + X_Node_CSS__Util.pxTo( v, u ) + u )
811 return new Property( p, X_Node_CSS__Util.pxTo( v, u ), u, xnode );
813 if( p === 'fontSize' && ( v = X_Node_CSS__FONT_SIZE_RATIO[ x ] ) ){ // xx-small 等
814 return new Property( p, v, 'px', xnode );
816 if( PARAMS.offset[ p ] || PARAMS.percent[ p ] || PARAMS.size[ p ] ){
817 vu = X_Node_CSS__splitValueAndUnit( x );
818 return new Property( p, vu[ 0 ], vu[ 1 ], xnode );
821 if( PARAMS.color[ p ] ) return new ColorProperty( p, x );
824 function X_Node_CSS__splitValueAndUnit( v ){
826 if( X.Type.isNumber( v ) ) return [ v || 0, '' ];
827 if( isNaN( num = parseFloat( v ) ) ) return [ 0, '' ];
829 if( _num.indexOf( '0.' ) === 0 ) _num = _num.slice( 1 );
830 u = v.substr( v.indexOf( _num ) + _num.length );
831 return [ num, X_Node_CSS_UNIT[ u ] ? u : 'px' ];
834 var X_Node_CSS__GET_VALUE_WITH_UNIT = {
835 borderWidth : X_Node_CSS_Type.QUARTET | X_Node_CSS_Type.LENGTH,
836 //borderStyle : X_Node_CSS_Type.QUARTET,
837 borderRadius : X_Node_CSS_Type.QUARTET | X_Node_CSS_Type.LENGTH,
838 margin : X_Node_CSS_Type.QUARTET | X_Node_CSS_Type.LENGTH | X_Node_CSS_Type.PERCENT,
839 padding : X_Node_CSS_Type.QUARTET | X_Node_CSS_Type.LENGTH | X_Node_CSS_Type.PERCENT,
840 clip : X_Node_CSS_Type.QUARTET | X_Node_CSS_Type.LENGTH | X_Node_CSS_Type.PERCENT,
842 backgroundColor : X_Node_CSS_Type.COLOR,
843 backgroundPosition : X_Node_CSS_Type.COMBI,
847 fontSize : X_Node_CSS_Type.LENGTH,
848 lineHeight : X_Node_CSS_Type.LENGTH | X_Node_CSS_Type.PERCENT | X_Node_CSS_Type.NUMERICAL,
849 textIndent : X_Node_CSS_Type.LENGTH,
850 letterSpacing : X_Node_CSS_Type.LENGTH,
851 wordSpacing : X_Node_CSS_Type.LENGTH,
853 textShadowColor : X_Node_CSS_Type.COLOR,
854 textShadowOffsetX : X_Node_CSS_Type.LENGTH,
855 textShadowOffsetY : X_Node_CSS_Type.LENGTH,
856 textShadowBlur : X_Node_CSS_Type.LENGTH, */
858 width : X_Node_CSS_Type.LENGTH | X_Node_CSS_Type.PERCENT,
859 height : X_Node_CSS_Type.LENGTH | X_Node_CSS_Type.PERCENT,
861 left : X_Node_CSS_Type.LENGTH | X_Node_CSS_Type.PERCENT,
862 top : X_Node_CSS_Type.LENGTH | X_Node_CSS_Type.PERCENT,
863 bottom : X_Node_CSS_Type.LENGTH | X_Node_CSS_Type.PERCENT,
864 right : X_Node_CSS_Type.LENGTH | X_Node_CSS_Type.PERCENT,
867 borderSpacing : X_Node_CSS_Type.LENGTH
871 var X_Node_CSS_SPECIAL_FIX =
873 X_UA.IE && X_UA.IE < 9 && !X_UA.MacIE?
875 var test = X_Node_CSS_SPECIAL_FIX_PROP,
880 if( !( id = test[ p ] ) ) continue;
883 case 1 : //'filter' :
886 case 2 : //'opacity' :
887 filters[ ++n ] = 'alpha(opacity=' + v * 100 +')';
889 case 3 : //'boxShadow' :
890 // box-shadow: 10px 10px 10px 10px rgba(0,0,0,0.4) inset;
891 // スペース区切りで、水平方向の距離 垂直方向の距離 ぼかし距離 広がり距離 影の色 insetキーワードを指定する。 ぼかし距離 広がり距離 影の色 insetキーワードは省略可
892 // shadow(color=#cccccc, strength=10, direction=135);
893 v = X_Node_CSS__getProperty( this, css, 'px', 'boxShadow' );
894 dir = Math.atan2( v[ 1 ], v[ 0 ] ) * 180 / Math.PI + 90;
895 dir += dir < 0 ? 360 : 0;
896 filters[ ++n ] = 'shadow(color=' + v[ 4 ] + ',strength=' + v[ 3 ] + ',direction=' + dir + ')';
898 case 4 : //'textShadow' :
899 //text-shadow: 5px 5px 2px blue; 水平方向の距離 垂直方向の距離 影のぼかし半径 影の色 none
900 //glow(Color=yellow,Strength=10);
901 //どうやらCSSのbackgroundプロパティと同時に使えないようです。
905 case 5 : //'backgroundImage' :
909 return filters.join( ' ' );
911 // IE9 textShadow に filter を使用
912 X_UA.IE && 9 <= X_UA.IE && X_UA.IE < 10 ?
914 var test = X_Node_CSS_SPECIAL_FIX_PROP,
915 filters = [], p, id, v;
917 if( !( id = test[ p ] ) ) continue;
920 case 1 : //'filter' :
921 filters[ filters.length ] = v;
925 if( filters ) return filters.join( ' ' );
928 var test = X_Node_CSS_SPECIAL_FIX_PROP,
929 ret = [], p, id, v, bgpX, bgpY, clipT, clipB, clipL, clipR;
931 if( !( id = test[ p ] ) ) continue;
934 case 1 : //'backgroundPositionX' :
937 case 2 : //'backgroundPositionY' :
940 case 3 : //'backgroundPositionX' :
943 case 4 : //'backgroundPositionX' :
946 case 5 : //'backgroundPositionX' :
949 case 6 : //'backgroundPositionX' :
954 if( bgpX || bgpY ) ret[ ret.length ] = 'background-position:';
955 if( clipT || clipB || clipL || clipR ){
956 ret[ ret.length ] = 'clip:rect(';
958 return ret.join( ';' );
966 // unitID, name 単位指定のプロパティ取得 geter
968 // name, value setter
970 Node.prototype.css = function( nameOrObj /* orUnitID, valuOrUnitOrName */ ){
971 var args = arguments,
973 p, name, v, camelize, unit, ieFix;
974 if( this._xnodeType !== 1 ) return this;
976 if( X.Type.isObject( nameOrObj ) ){
977 if( !css ) css = this._css = {};
978 camelize = X_Node_CSS_camelize;
979 ieFix = X_Node_CSS_IE_FILTER_FIX;
980 for( p in nameOrObj ){
982 this._dirty |= X_Node_Dirty.IE_FILTER;
985 v || v === 0 ? css[ camelize( p ) ] = v : delete css[ camelize( p ) ];
986 if( p === 'display' ){
987 v === 'none' ? ( this._state |= X_Node_State.IE5_DISPLAY_NONE_FIX ) : ( this._state &= ~X_Node_State.IE5_DISPLAY_NONE_FIX );
988 v === 'none' ? ( this._state |= X_Node_State.DISPLAY_NONE ) : ( this._state &= ~X_Node_State.DISPLAY_NONE );
991 this._dirty |= X_Node_Dirty.CSS;
992 this.parent && X_Node_reserveUpdate();
993 delete this._cssText;
996 if( 1 < args.length ){
997 if( !X_Node_CSS_UNIT[ nameOrObj ] ){
998 // setter name, value
999 if( !css ) css = this._css = {};
1000 name = X_Node_CSS_camelize( nameOrObj );
1002 if( css[ name ] === v ) return this;
1003 if( X_Node_CSS_IE_FILTER_FIX[ name ] ){
1004 this._dirty |= X_Node_Dirty.IE_FILTER;
1006 if( !v && v !== 0 ){
1011 delete this._cssText;
1012 this._dirty |= X_Node_Dirty.CSS;
1013 if( name === 'display' ){
1014 v === 'none' ? ( this._state |= X_Node_State.IE5_DISPLAY_NONE_FIX ) : ( this._state &= ~X_Node_State.IE5_DISPLAY_NONE_FIX );
1015 v === 'none' ? ( this._state |= X_Node_State.DISPLAY_NONE ) : ( this._state &= ~X_Node_State.DISPLAY_NONE );
1017 // parent でなく this._root! でなくて this._state & in tree
1018 this.parent && X_Node_reserveUpdate();
1022 // unit 付の値取得は fontSize と 画像サイズが確定していないと正確に取れない。内部のみにする?
1024 if( !X_Node_CSS__GET_VALUE_WITH_UNIT[ name = X_Node_CSS_camelize( args[ 1 ] ) ] ) return null;
1025 p = X_Node_CSS__getProperty( this, css, nameOrObj, name );
1026 v = p.pxTo( nameOrObj );
1032 // 集計 border, padding, margin, backgroundPosition, clip
1033 // border で正確なデータを返せない時は、null を返す
1034 return css[ X_Node_CSS_camelize( nameOrObj ) ];
1037 Node.prototype.cssText = function( v ){
1038 var obj, i, l, attr, name;
1041 this._state &= ~X_Node_State.IE5_DISPLAY_NONE_FIX;
1042 this._dirty |= X_Node_Dirty.CSS;
1043 this.parent && X_Node_reserveUpdate();
1044 delete this._cssText;
1047 if( X.Type.isString( v ) ){
1049 this._state &= ~X_Node_State.IE5_DISPLAY_NONE_FIX;
1051 v = v.split( ';' ); // TODO content ";" などにも対応
1052 for( i = 0, l = v.length; i < l; ++i ){
1053 attr = v[ i ].split( ':' );
1054 ( name = attr[ 0 ] ) && ( obj[ name ] = attr[ 1 ] || true );
1056 return this.css( obj );
1059 if( this._dirty & X_Node_Dirty.CSS && !( this._cssText = X_Node_CSS_objToCssText( this._css ) ) ){
1060 delete this._cssText;
1062 return this._cssText;
1066 * ここでは HTMLElement のチ1ェックは行わない!
1068 * body に css attr がセットされた場合には X_ViewPort_baseFontSize をクリア
1071 Node.prototype._getCharSize =
1072 window.getComputedStyle ?
1074 X_Node_body._updateTimerID && X_Node_startUpdate();
1075 if( this === X_Node_body && X_ViewPort_baseFontSize ) return X_ViewPort_baseFontSize;
1076 if( this._fontSize ) return this._fontSize;
1077 return this._fontSize = parseFloat( getComputedStyle( this._rawObject, null ).fontSize );
1080 document.defaultView && document.defaultView.getComputedStyle ?
1082 X_Node_body._updateTimerID && X_Node_startUpdate();
1083 if( this === X_Node_body && X_ViewPort_baseFontSize ) return X_ViewPort_baseFontSize;
1084 if( this._fontSize ) return this._fontSize;
1085 return this._fontSize = parseFloat( document.defaultView.getComputedStyle( this._rawObject, null ).fontSize );
1090 var font, vu, v, u, _v;
1091 X_Node_body._updateTimerID && X_Node_startUpdate();
1092 if( this === X_Node_body && X_ViewPort_baseFontSize ) return X_ViewPort_baseFontSize;
1093 if( this._fontSize ) return this._fontSize;
1095 font = this._rawObject.currentStyle.fontSize;
1096 //font = this._css && this._css.fontSize || '1em';
1097 vu = X_Node_CSS__splitValueAndUnit( font );
1102 if( v = X_Node_CSS__FONT_SIZE_RATIO[ font ] ) return this._fontSize = v;
1104 if( _v = X_Node_CSS__UNIT_RATIO[ u ] ) return this._fontSize = v / _v;
1108 return this._fontSize = v;
1110 // body まで辿ってしまった場合は?
1111 if( this.parent ) return this._fontSize = this.parent._getCharSize() * v;
1114 // body まで辿ってしまった場合は?
1115 if( this.parent ) return this._fontSize = this.parent._getCharSize() * v / 100;
1122 X_Node_body._updateTimerID && X_Node_startUpdate();
1123 if( this === X_Node_body && X_ViewPort_baseFontSize ) return X_ViewPort_baseFontSize;
1124 if( this._fontSize ) return this._fontSize;
1126 this._rawObject.appendChild( elm = document.createElement( 'span' ) );
1127 elm.style.cssText = 'display:block;position:absolute;top:0;left:0;visivility:hidden;line-height:1;height:1em;';
1128 elm.innerHTML = 'X';
1129 v = elm.offsetHeight;
1130 this._rawObject.removeChild( elm );
1131 return this._fontSize = v;
1135 var font, vu, v, u, _v;
1136 X_Node_body._updateTimerID && X_Node_startUpdate();
1137 if( this === X_Node_body && X_ViewPort_baseFontSize ) return X_ViewPort_baseFontSize;
1138 if( this._fontSize ) return this._fontSize;
1140 if( this._css && ( font = this._css.fontSize ) ){
1141 vu = X_Node_CSS__splitValueAndUnit( font );
1146 if( _v = X_Node_CSS__FONT_SIZE_RATIO[ font ] ) return this._fontSize = _v;
1148 if( _v = X_Node_CSS__UNIT_RATIO[ u ] ) return this._fontSize = v / _v;
1157 return this._fontSize = v;
1159 // body まで辿ってしまった場合は?
1160 if( this.parent ) return this._fontSize = this.parent._getCharSize() * v;
1163 // body まで辿ってしまった場合は?
1164 if( this.parent ) return this._fontSize = this.parent._getCharSize() * v / 100;
1171 if( this === X_Node_body && X_ViewPort_baseFontSize ) return X_ViewPort_baseFontSize;
1172 X_Node_body._updateTimerID && X_Node_startUpdate();
1173 if( this._fontSize ) return this._fontSize;
1175 elm = this._rawObject;
1176 elm.insertAdjacentHTML( 'BeforeEnd', '<span style="visivility:hidden;line-height:1;">X</span>' );
1177 elm = elm.children[ elm.children.length - 1 ];
1178 v = elm.offsetHeight;
1180 return this._fontSize = v * 0.75;
1186 VENDER_PREFIX : X_Node_CSS_VENDER_PREFIX,
1188 parseColor : X_Node_CSS_parseColor,
1190 uncamelize : X_Node_CSS_uncamelize
1195 var X_Node_CSS_Support, X_Node_CSS_SPECIAL_FIX_PROP;
1198 var testStyle = X_UA.IE4 ? {} : ( document.documentElement || document.createElement( 'div' ) ).style,
1199 temp = testStyle.cssText,
1200 prefix = X_Node_CSS_VENDER_PREFIX,
1201 vendors = 'webkit,Webkit,Moz,moz,Ms,ms,O,o,khtml,Khtml'.split( ',' ),
1203 'opacity,boxSizing,' +
1204 'transform,transformOrigin,perspective,' +
1205 'transisiton,transitionDelay,transitionProperty,transitionDuration,transitionTimingFunction,' +
1206 'userSelect,touchSelect,touchAction,touchCallout,contentZooming,userDrag,tapHighlightColor' ).split( ',' ),
1207 vendor, i, search, prop, j, v;
1209 for( i = searches.length; i; ){
1210 search = prop = searches[ --i ];
1212 if( testStyle[ prop ] === undefined ){
1213 prop = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 );
1214 for( j = vendors.length; j; ){
1216 if( testStyle[ v + prop ] !== undefined ){
1217 if( v === 'ms' ) v = 'Ms';// for ie9
1218 if( v === 'o' ) v = 'O';//for opera12
1219 prefix[ search ] = v + prop;
1224 prefix[ search ] = prop;
1228 testStyle.cssText = 'background:rgba(0,0,0,0.5)';
1230 X.CSS.Support = X_Node_CSS_Support = {
1231 rgba : !!testStyle.background
1234 testStyle.cssText = temp;
1236 X_Node_CSS_SPECIAL_FIX_PROP =
1238 X_UA.IE < 9 && !X_UA.MacIE ?
1241 opacity : 2//, uinode ChromeNode で行う
1244 //backgroundImage : 5
1247 9 <= X_UA.IE && X_UA.IE < 10 ?
1253 backgroundPositionX : testStyle.backgroundPositionX === undefined ? 3 : 0,
1254 backgroundPosiitonY : testStyle.backgroundPositionX === undefined ? 3 : 0,
1255 clipTop : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 3 : 0,
1256 clipBottom : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 4 : 0,
1257 clipLeft : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 5 : 0,
1258 clipRight : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 6 : 0
1262 X_ViewPort.listenOnce( X_TEMP.SYSTEM_EVENT_INIT, function(){
1263 var xnode = X_Node_systemNode,
1264 output = X_Node_CSS__UNIT_RATIO,
1265 list = 'cm,mm,in,pt,pc'.split( ',' ),
1266 unit, size, base, i;
1268 for( i = list.length; i; ){
1270 output[ unit ] = xnode.css( 'width', 10 + unit ).width() / 10;
1273 output = X_Node_CSS__FONT_SIZE_RATIO,
1274 list = 'xx-large,x-large,large,larger,medium,small,smaller,x-small,xx-small'.split( ',' );
1275 xnode.css( { lineHeight : '100%', height : '1em' } ).text( 'X' );
1277 for( i = list.length; i; ){
1279 output[ size ] = xnode.css( 'fontSize', size ).height();// / base;
1282 xnode.cssText( '' ).empty();