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%
51 /* font-size -> fontSize */
52 _DICTIONARY_CAMELIZE : {},
54 camelize : function( cssProp ){
56 parts, l, i, camelized;
58 if( camelized = me._DICTIONARY_CAMELIZE[ cssProp ] ) return camelized;
59 parts = cssProp.split( ' ' ).join( '' ).split( '-' );
61 if( l === 1 ) return parts[ 0 ];
63 camelized = cssProp.charAt(0) === '-'
64 ? parts[ 0 ].charAt( 0 ).toUpperCase() + parts[ 0 ].substring( 1 )
67 for( i = 1; i < l; ++i ){
68 camelized += parts[ i ].charAt( 0 ).toUpperCase() + parts[ i ].substring( 1 );
70 return me._DICTIONARY_CAMELIZE[ cssProp ] = camelized;
73 /* fontSize -> font-size */
76 uncamelize: function( str ){
77 return str.split( ' ' ).join( '' ).replace( X.Dom.Style.REG_LARGE, '-$&' ).toLowerCase();
80 CHAR_CODE_A : 'A'.charCodeAt( 0 ),
82 _DICTIONARY_UNCAMELIZE : {},
84 uncamelize : function( str ){
88 uncamelized, l, chr, code;
89 str = str.split( ' ' ).join( '' );
90 if( uncamelized = me._DICTIONARY_UNCAMELIZE[ str ] ) return uncamelized;
92 for( i = 0, l = str.length; i < l; ++i ){
93 chr = str.charAt( i );
94 code = chr.charCodeAt( 0 );
95 uncamelized += ( A <= code && code <= Z ) ? '-' + chr : chr;
97 return me._DICTIONARY_UNCAMELIZE[ str ] = uncamelized.toLowerCase();
100 objToCssText : function( obj ){
103 uncamelize = me.uncamelize,
104 VENDER_PREFIX = me.VENDER_PREFIX,
105 FIX_PROP = me.SPECIAL_FIX_PROP,
106 SPECIAL_FIX = me.SPECIAL_FIX,
109 name = uncamelize( p );
110 if( FIX_PROP[ name ] ){
113 css[ css.length ] = [ VENDER_PREFIX[ name ] || name, obj[ p ] ].join( ':' );
116 sp && ( css[ css.length ] = SPECIAL_FIX( obj ) );
117 return css.join( ';' );
120 _FONT_SIZE_RATIO : {},
122 absoluteFontSizeToPx : function( fontsize ){
123 return X.Dom.Style._FONT_SIZE_RATIO[ fontsize ] || 0;
126 // https://developer.mozilla.org/en-US/docs/Web/CSS/transform
127 // Firefox 3.5, ie9, Opera 10.5, Safari 3.1, Chrome
128 // 3D support Firefox 10, ie10, Safari 4.0, Chrome 12.0
129 // transform : void 0,
131 // https://developer.mozilla.org/ja/docs/Web/Guide/CSS/Using_CSS_transitions
132 // Chrome 1.0, Firefox 4.0, ie10, Opera 10.5, Safari 3.2
133 // Android 2.1, Firefox Android 4.0, Opera Mobile 10, Safari Mobile 3.2
134 // transition : void 0
137 X.Dom.Style.Option = {
138 BORDER_STYLE : 'none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset'.split(','),
139 POSITION_X : 'left,center,right'.split(','),
140 POSITION_Y : 'top,center,bottom'.split(','),
141 ALIGN : 'left,center,right,justify'.split(','),
142 TEXT_DECORATION : 'none,underline,overline,line-through,blink'.split(','),
143 TEXT_TRANSFORM : 'none,capitalize,lowercase,uppercase'.split(','),
144 WIDTH_HEIGHT : [ 'auto' ],
145 BOX_SIZING : 'content-box,padding-box,border-box'.split(',') // ,margin-box
147 X.Dom.Style.Props = {
148 borderWidth : [ X.Dom.Dirty.REFLOW, 0, X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH ], // em [ top, right, bottom, left ]
149 borderColor : [ X.Dom.Dirty.PAINT, 4, X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.COLOR ], // color [ top, right, bottom, left ]
150 borderStyle : [ X.Dom.Dirty.PAINT, 8, X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LIST, X.Dom.Style.Option.BORDER_STYLE ], // string [ top, right, bottom, left ]
151 cornerRadius : [ X.Dom.Dirty.PAINT, 12, X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ], // em, px [ top, right, bottom, left ]
152 bgColor : [ X.Dom.Dirty.PAINT, 16, X.Dom.Style.Type.COLOR ], // color
153 bgAlpha : [ X.Dom.Dirty.PAINT, 17, X.Dom.Style.Type.U_DECIMAL ], // 0 - 1
154 bgImgUrl : [ X.Dom.Dirty.PAINT, 18, X.Dom.Style.Type.URL ], // url
155 bgImgRepeatX : [ X.Dom.Dirty.PAINT, 19, X.Dom.Style.Type.BOOLEAN ], // true / false
156 bgImgRepeatY : [ X.Dom.Dirty.PAINT, 20, X.Dom.Style.Type.BOOLEAN ], // true / false
157 bgImgPositionX : [ X.Dom.Dirty.PAINT, 21, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT | X.Dom.Style.Type.LIST, X.Dom.Style.Option.POSITION_X ], // em %, px, string
158 bgImgPositionY : [ X.Dom.Dirty.PAINT, 22, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT | X.Dom.Style.Type.LIST, X.Dom.Style.Option.POSITION_Y ], // em %, px, string
159 shadowColor : [ X.Dom.Dirty.PAINT, 23, X.Dom.Style.Type.COLOR ], // color
160 shadowAlpha : [ X.Dom.Dirty.PAINT, 24, X.Dom.Style.Type.U_DECIMAL ], // 0 - 1
161 shadowOffsetX : [ X.Dom.Dirty.PAINT, 25, X.Dom.Style.Type.LENGTH ], // em
162 shadowOffsetY : [ X.Dom.Dirty.PAINT, 26, X.Dom.Style.Type.LENGTH ], // em
163 shadowBlur : [ X.Dom.Dirty.PAINT, 27, X.Dom.Style.Type.LENGTH ], // em
164 shadowSpread : [ X.Dom.Dirty.PAINT, 28, X.Dom.Style.Type.LENGTH ], // em
165 shadowInset : [ X.Dom.Dirty.PAINT, 29, X.Dom.Style.Type.BOOLEAN ], // true / false
167 color : [ X.Dom.Dirty.PAINT, 30, X.Dom.Style.Type.COLOR ], // color
168 fontFamily : [ X.Dom.Dirty.FONT, 31, X.Dom.Style.Type.FONT_NAME ], // string
169 fontSize : [ X.Dom.Dirty.FONT, 32, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ], // em, %
170 bold : [ X.Dom.Dirty.FONT, 33, X.Dom.Style.Type.BOOLEAN ], // true / false
171 italic : [ X.Dom.Dirty.FONT, 34, X.Dom.Style.Type.BOOLEAN ], // true / false
172 lineHeight : [ X.Dom.Dirty.FONT, 35, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT | X.Dom.Style.Type.NUMERICAL ], // em, %,
173 letterSpacing : [ X.Dom.Dirty.FONT, 36, X.Dom.Style.Type.LENGTH ], // em
174 wordSpacing : [ X.Dom.Dirty.FONT, 37, X.Dom.Style.Type.LENGTH ],
175 align : [ X.Dom.Dirty.FONT, 38, X.Dom.Style.Type.LIST, X.Dom.Style.Type.ALIGN ],
176 decoration : [ X.Dom.Dirty.PAINT, 39, X.Dom.Style.Type.LIST, X.Dom.Style.Type.TEXT_DECORATION ],
177 transform : [ X.Dom.Dirty.FONT, 40, X.Dom.Style.Type.LIST, X.Dom.Style.Type.TEXT_TRANSFORM ],
178 textShadowColor : [ X.Dom.Dirty.PAINT, 41, X.Dom.Style.Type.COLOR ],
179 textShadowOffsetX : [ X.Dom.Dirty.PAINT, 42, X.Dom.Style.Type.LENGTH ],
180 textShadowOffsetY : [ X.Dom.Dirty.PAINT, 43, X.Dom.Style.Type.LENGTH ],
181 shadowBlur : [ X.Dom.Dirty.PAINT, 44, X.Dom.Style.Type.LENGTH ],
183 width : [ X.Dom.Dirty.REFLOW, 45, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT, X.Dom.Style.Option.WIDTH_HEIGHT ],
184 minWidth : [ X.Dom.Dirty.REFLOW, 46, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
185 maxWidth : [ X.Dom.Dirty.REFLOW, 47, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
186 height : [ X.Dom.Dirty.REFLOW, 48, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT, X.Dom.Style.Option.WIDTH_HEIGHT ],
187 minHeight : [ X.Dom.Dirty.REFLOW, 49, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
188 maxHeight : [ X.Dom.Dirty.REFLOW, 50, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
189 padding : [ X.Dom.Dirty.REFLOW, 51, X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
190 margin : [ X.Dom.Dirty.REFLOW, 55, X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
191 sizing : [ X.Dom.Dirty.REFLOW, 59, X.Dom.Style.Type.LIST, X.Dom.Style.Option.BOX_SIZING ],
192 pageBox : [ X.Dom.Dirty.REFLOW, 60, X.Dom.Style.Type.BOOLEAN ], // true / false
193 left : [ X.Dom.Dirty.REFLOW, 61, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
194 top : [ X.Dom.Dirty.REFLOW, 62, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
195 bottom : [ X.Dom.Dirty.REFLOW, 63, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
196 right : [ X.Dom.Dirty.REFLOW, 64, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ]
199 X.Dom.Style.SPECIAL_FIX =
201 X.UA.IE && X.UA.IE < 9 ?
203 var test = X.Dom.Style.SPECIAL_FIX_PROP,
204 filters = [], p, id, v;
206 if( !( id = test[ p ] ) ) continue;
209 case 1 : //'filter' :
210 filters[ filters.length ] = v;
212 case 2 : //'opacity' :
213 filters[ filters.length ] = 'aplha(opacity=' + v +')';
215 case 3 : //'boxShadow' :
216 // box-shadow: 10px 10px 10px 10px rgba(0,0,0,0.4) inset;
217 // スペース区切りで、水平方向の距離 垂直方向の距離 ぼかし距離 広がり距離 影の色 insetキーワードを指定する。 ぼかし距離 広がり距離 影の色 insetキーワードは省略可
218 // shadow(color=#cccccc, strength=10, direction=135);
219 parseValue( 'boxShadow', v, 'px' );
220 dir = Math.atan2( ary[1], ary[0] ) * 180 / Math.PI + 90;
221 dir += dir < 0 ? 360 : 0;
223 case 4 : //'textShadow' :
224 //text-shadow: 5px 5px 2px blue; 水平方向の距離 垂直方向の距離 影のぼかし半径 影の色 none
225 //glow(Color=yellow,Strength=10);
226 //どうやらCSSのbackgroundプロパティと同時に使えないようです。
228 case 5 : //'backgroundImage' :
232 if( filters ) return filters.join( ' ' );
235 X.UA.IE && 9 <= X.UA.IE && X.UA.IE < 10 ?
237 var test = X.Dom.Style.SPECIAL_FIX_PROP,
238 filters = [], p, id, v;
240 if( !( id = test[ p ] ) ) continue;
243 case 1 : //'filter' :
244 filters[ filters.length ] = v;
248 if( filters ) return filters.join( ' ' );
251 var test = X.Dom.Style.SPECIAL_FIX_PROP,
254 if( !( id = test[ p ] ) ) continue;
257 case 1 : //'backgroundPositionX' :
260 case 2 : //'backgroundPositionY' :
263 case 3 : //'backgroundPositionX' :
266 case 4 : //'backgroundPositionX' :
269 case 5 : //'backgroundPositionX' :
272 case 6 : //'backgroundPositionX' :
277 if( bgpX || bgpY ) ret[ ret.length ] = 'background-position:';
278 if( clipT || clipB || clipL || clipR ){
279 ret[ ret.length ] = 'clip:rect(';
281 return ret.join( ';' );
289 // unitID, name 単位指定のプロパティ取得 geter
291 // name, value setter
292 X.Dom.Node.prototype.css = function( nameOrObj /* orUnitID, valuOrUnitOrName */ ){
293 var XDomStyle = X.Dom.Style,
296 p, valOrUnit, name, v, node, camelize;
297 if( this._nodeType !== 1 ) return this;
299 if( X.Type.isObject( nameOrObj ) ){
300 if( !css ) css = this._css = {};
301 camelize = XDomStyle.camelize;
302 for( p in nameOrObj ){
303 css[ camelize( p ) ] = nameOrObj[ p ];
305 this._cssText = XDomStyle.objToCssText( this._css );
306 if( node = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode ){
308 node.style.cssText = this._cssText;
310 node.removeAttribute( 'style' );
315 if( 1 < args.length && !XDomStyle.UNIT[ nameOrObj ] ){
316 if( !css ) css = this._css = {};
317 name = XDomStyle.camelize( nameOrObj );
319 if( css[ name ] === v ) return this;
320 if( node = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode ){
321 node.style[ name ] = v; // val
324 this._cssText = [ this._cssText, this._cssText ? ';' : '', XDomStyle.uncamelize( nameOrObj ), ':', v ].join( '' );
329 this._cssText = XDomStyle.objToCssText( css );
331 node && !this._cssText && node.removeAttribute( 'style' );
336 if( 1 < args.length && XDomStyle.UNIT[ nameOrObj ] ){ // unit
338 return XDomStyle.getValue( this, args[ 1 ], name );
340 // 集計 border, padding, margin, backgroundPosition, clip
341 // border で正確なデータを返せない時は、null を返す
342 return css[ XDomStyle.camelize( nameOrObj ) ];
345 X.Dom.Node.prototype.cssText = function( v ){
346 var camelize, obj, i, l, attr, name;
347 if( X.Type.isString( v ) ){
348 camelize = X.Dom.Style.camelize;
352 for( i = 0, l = v.length; i < l; ++i ){
353 attr = v[ i ].split( ':' );
354 name = camelize( attr[ 0 ] );
355 name && ( obj[ name ] = attr[ 1 ] || true );
357 return this.css( obj );
359 return this._cssText;
362 X.Dom.Node.prototype._getCharSize =
363 document.defaultView && document.defaultView.getComputedStyle ?
365 document.defaultView.getComputedStyle( this._rawNode, null );
367 X.UA.IE && 5 <= X.UA.IE ?
369 //this._rawNode.currentStyle;
371 document.removeChild ?
379 X.Dom.listenOnce( X.Dom.Event.DOM_PREINIT, function(){
381 var testStyle = X.Dom._view;
383 X.Dom.Style.VENDER_PREFIX = (function(){
385 vendors = ',webkit,Webkit,Moz,moz,ms,Ms,O,o,khtml,Khtml'.split( ',' ),
387 'opacity,boxSizing,' +
388 'transform,transformOrigin,perspective,' +
389 'transisiton,transitionDelay,transitionProperty,transitionDuration,transitionTimingFunction,' +
390 'userSelect,touchAction,touchCallout,contentZooming,userDrag,tapHighlightColor'.split( ',' ),
391 vendor, i, search, prop;
393 function findVenderPrefix( prop ){
394 var v, i = vendors.length;
398 if( testStyle[ v + prop ] !== undefined ){
405 for( i = searches.length; i; ){
406 search = searches[ --i ];
407 prop = findVenderPrefix( search );
408 if( search === 'transform' ) ret.transVender = vendor;
409 if( prop ) ret[ search ] = prop;
414 X.Dom.Style.SPECIAL_FIX_PROP =
416 X.UA.IE && X.UA.IE < 9 ?
419 opacity : 2//, uinode ChromeNode で行う
422 //backgroundImage : 5
425 X.UA.IE && 9 <= X.UA.IE && X.UA.IE < 10 ?
431 backgroundPositionX : testStyle.backgroundPositionX === undefined ? 3 : 0,
432 backgroundPosiitonY : testStyle.backgroundPositionX === undefined ? 3 : 0,
433 clipTop : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 3 : 0,
434 clipBottom : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 4 : 0,
435 clipLeft : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 5 : 0,
436 clipRight : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 6 : 0
440 X.Dom.listenOnce( X.Dom.Event.DOM_INIT, function(){
441 var xnode = Node._systemNode;
443 var ret = X.Dom.Style._UNIT_RATIO = {},
445 units = 'em,cm,mm,in,pt,pc'.split( ',' ),
450 xnode.css( 'width', 100 + unit );
451 ret[ unit ] = xnode.width() / 100;
452 console.log( unit + ':' + ret[ unit ] );
454 xnode.css( 'width', '' );
456 var ret = X.Dom.Style._FONT_SIZE_RATIO = {},
458 list = 'xx-large,x-large,large,larger,medium,small,smaller,x-small,xx-small'.split( ',' ),
461 base = xnode.css( 'lineHeight', 1 ).text( 'X' ).height();
464 ret[ size ] = xnode.css( 'fontSize', size ).height() / base;
465 console.log( size + ':' + ( ret[ size ] * 100 | 0 ) + '%' );
468 xnode.empty().cssText( '' );