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( ';' );
121 _FONT_SIZE_RATIO : null,
123 absoluteFontSizeToPx : function( fontsize ){
124 return X.Dom.Style._FONT_SIZE_RATIO[ fontsize ] || 0;
127 // https://developer.mozilla.org/en-US/docs/Web/CSS/transform
128 // Firefox 3.5, ie9, Opera 10.5, Safari 3.1, Chrome
129 // 3D support Firefox 10, ie10, Safari 4.0, Chrome 12.0
130 // transform : void 0,
132 // https://developer.mozilla.org/ja/docs/Web/Guide/CSS/Using_CSS_transitions
133 // Chrome 1.0, Firefox 4.0, ie10, Opera 10.5, Safari 3.2
134 // Android 2.1, Firefox Android 4.0, Opera Mobile 10, Safari Mobile 3.2
135 // transition : void 0
138 X.Dom.Style.Option = {
139 BORDER_STYLE : 'none,hidden,dotted,dashed,solid,double,groove,ridge,inset,outset'.split(','),
140 POSITION_X : 'left,center,right'.split(','),
141 POSITION_Y : 'top,center,bottom'.split(','),
142 ALIGN : 'left,center,right,justify'.split(','),
143 TEXT_DECORATION : 'none,underline,overline,line-through,blink'.split(','),
144 TEXT_TRANSFORM : 'none,capitalize,lowercase,uppercase'.split(','),
145 WIDTH_HEIGHT : [ 'auto' ],
146 BOX_SIZING : 'content-box,padding-box,border-box'.split(',') // ,margin-box
148 X.Dom.Style.Props = {
149 borderWidth : [ X.Dom.Dirty.REFLOW, 0, X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH ], // em [ top, right, bottom, left ]
150 borderColor : [ X.Dom.Dirty.PAINT, 4, X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.COLOR ], // color [ top, right, bottom, left ]
151 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 ]
152 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 ]
153 bgColor : [ X.Dom.Dirty.PAINT, 16, X.Dom.Style.Type.COLOR ], // color
154 bgAlpha : [ X.Dom.Dirty.PAINT, 17, X.Dom.Style.Type.U_DECIMAL ], // 0 - 1
155 bgImgUrl : [ X.Dom.Dirty.PAINT, 18, X.Dom.Style.Type.URL ], // url
156 bgImgRepeatX : [ X.Dom.Dirty.PAINT, 19, X.Dom.Style.Type.BOOLEAN ], // true / false
157 bgImgRepeatY : [ X.Dom.Dirty.PAINT, 20, X.Dom.Style.Type.BOOLEAN ], // true / false
158 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
159 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
160 shadowColor : [ X.Dom.Dirty.PAINT, 23, X.Dom.Style.Type.COLOR ], // color
161 shadowAlpha : [ X.Dom.Dirty.PAINT, 24, X.Dom.Style.Type.U_DECIMAL ], // 0 - 1
162 shadowOffsetX : [ X.Dom.Dirty.PAINT, 25, X.Dom.Style.Type.LENGTH ], // em
163 shadowOffsetY : [ X.Dom.Dirty.PAINT, 26, X.Dom.Style.Type.LENGTH ], // em
164 shadowBlur : [ X.Dom.Dirty.PAINT, 27, X.Dom.Style.Type.LENGTH ], // em
165 shadowSpread : [ X.Dom.Dirty.PAINT, 28, X.Dom.Style.Type.LENGTH ], // em
166 shadowInset : [ X.Dom.Dirty.PAINT, 29, X.Dom.Style.Type.BOOLEAN ], // true / false
168 color : [ X.Dom.Dirty.PAINT, 30, X.Dom.Style.Type.COLOR ], // color
169 fontFamily : [ X.Dom.Dirty.FONT, 31, X.Dom.Style.Type.FONT_NAME ], // string
170 fontSize : [ X.Dom.Dirty.FONT, 32, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ], // em, %
171 bold : [ X.Dom.Dirty.FONT, 33, X.Dom.Style.Type.BOOLEAN ], // true / false
172 italic : [ X.Dom.Dirty.FONT, 34, X.Dom.Style.Type.BOOLEAN ], // true / false
173 lineHeight : [ X.Dom.Dirty.FONT, 35, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT | X.Dom.Style.Type.NUMERICAL ], // em, %,
174 letterSpacing : [ X.Dom.Dirty.FONT, 36, X.Dom.Style.Type.LENGTH ], // em
175 wordSpacing : [ X.Dom.Dirty.FONT, 37, X.Dom.Style.Type.LENGTH ],
176 align : [ X.Dom.Dirty.FONT, 38, X.Dom.Style.Type.LIST, X.Dom.Style.Type.ALIGN ],
177 decoration : [ X.Dom.Dirty.PAINT, 39, X.Dom.Style.Type.LIST, X.Dom.Style.Type.TEXT_DECORATION ],
178 transform : [ X.Dom.Dirty.FONT, 40, X.Dom.Style.Type.LIST, X.Dom.Style.Type.TEXT_TRANSFORM ],
179 textShadowColor : [ X.Dom.Dirty.PAINT, 41, X.Dom.Style.Type.COLOR ],
180 textShadowOffsetX : [ X.Dom.Dirty.PAINT, 42, X.Dom.Style.Type.LENGTH ],
181 textShadowOffsetY : [ X.Dom.Dirty.PAINT, 43, X.Dom.Style.Type.LENGTH ],
182 shadowBlur : [ X.Dom.Dirty.PAINT, 44, X.Dom.Style.Type.LENGTH ],
184 width : [ X.Dom.Dirty.REFLOW, 45, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT, X.Dom.Style.Option.WIDTH_HEIGHT ],
185 minWidth : [ X.Dom.Dirty.REFLOW, 46, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
186 maxWidth : [ X.Dom.Dirty.REFLOW, 47, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
187 height : [ X.Dom.Dirty.REFLOW, 48, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT, X.Dom.Style.Option.WIDTH_HEIGHT ],
188 minHeight : [ X.Dom.Dirty.REFLOW, 49, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
189 maxHeight : [ X.Dom.Dirty.REFLOW, 50, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
190 padding : [ X.Dom.Dirty.REFLOW, 51, X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
191 margin : [ X.Dom.Dirty.REFLOW, 55, X.Dom.Style.Type.QUARTET | X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
192 sizing : [ X.Dom.Dirty.REFLOW, 59, X.Dom.Style.Type.LIST, X.Dom.Style.Option.BOX_SIZING ],
193 pageBox : [ X.Dom.Dirty.REFLOW, 60, X.Dom.Style.Type.BOOLEAN ], // true / false
194 left : [ X.Dom.Dirty.REFLOW, 61, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
195 top : [ X.Dom.Dirty.REFLOW, 62, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
196 bottom : [ X.Dom.Dirty.REFLOW, 63, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ],
197 right : [ X.Dom.Dirty.REFLOW, 64, X.Dom.Style.Type.LENGTH | X.Dom.Style.Type.PERCENT ]
200 X.Dom.Style.SPECIAL_FIX =
202 X.UA.IE && X.UA.IE < 9 ?
204 var test = X.Dom.Style.SPECIAL_FIX_PROP,
205 filters = [], p, id, v;
207 if( !( id = test[ p ] ) ) continue;
210 case 1 : //'filter' :
211 filters[ filters.length ] = v;
213 case 2 : //'opacity' :
214 filters[ filters.length ] = 'aplha(opacity=' + v +')';
216 case 3 : //'boxShadow' :
217 // box-shadow: 10px 10px 10px 10px rgba(0,0,0,0.4) inset;
218 // スペース区切りで、水平方向の距離 垂直方向の距離 ぼかし距離 広がり距離 影の色 insetキーワードを指定する。 ぼかし距離 広がり距離 影の色 insetキーワードは省略可
219 // shadow(color=#cccccc, strength=10, direction=135);
220 parseValue( 'boxShadow', v, 'px' );
221 dir = Math.atan2( ary[1], ary[0] ) * 180 / Math.PI + 90;
222 dir += dir < 0 ? 360 : 0;
224 case 4 : //'textShadow' :
225 //text-shadow: 5px 5px 2px blue; 水平方向の距離 垂直方向の距離 影のぼかし半径 影の色 none
226 //glow(Color=yellow,Strength=10);
227 //どうやらCSSのbackgroundプロパティと同時に使えないようです。
229 case 5 : //'backgroundImage' :
233 if( filters ) return filters.join( ' ' );
236 X.UA.IE && 9 <= X.UA.IE && X.UA.IE < 10 ?
238 var test = X.Dom.Style.SPECIAL_FIX_PROP,
239 filters = [], p, id, v;
241 if( !( id = test[ p ] ) ) continue;
244 case 1 : //'filter' :
245 filters[ filters.length ] = v;
249 if( filters ) return filters.join( ' ' );
252 var test = X.Dom.Style.SPECIAL_FIX_PROP,
255 if( !( id = test[ p ] ) ) continue;
258 case 1 : //'backgroundPositionX' :
261 case 2 : //'backgroundPositionY' :
264 case 3 : //'backgroundPositionX' :
267 case 4 : //'backgroundPositionX' :
270 case 5 : //'backgroundPositionX' :
273 case 6 : //'backgroundPositionX' :
278 if( bgpX || bgpY ) ret[ ret.length ] = 'background-position:';
279 if( clipT || clipB || clipL || clipR ){
280 ret[ ret.length ] = 'clip:rect(';
282 return ret.join( ';' );
290 // unitID, name 単位指定のプロパティ取得 geter
292 // name, value setter
293 X.Dom.Node.prototype.css = function( nameOrObj /* orUnitID, valuOrUnitOrName */ ){
294 var XDomStyle = X.Dom.Style,
297 p, valOrUnit, name, v, node, camelize;
298 if( this._xnodeType !== 1 ) return this;
300 if( X.Type.isObject( nameOrObj ) ){
301 if( !css ) css = this._css = {};
302 camelize = XDomStyle.camelize;
303 for( p in nameOrObj ){
304 css[ camelize( p ) ] = nameOrObj[ p ];
306 this._cssText = XDomStyle.objToCssText( this._css );
307 if( node = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode ){
309 node.style.cssText = this._cssText;
310 this._styleText = ' style="' + this._cssText + '"';
312 node.removeAttribute( 'style' );
313 delete this._cssText;
314 delete this._styleText;
319 if( 1 < args.length && !XDomStyle.UNIT[ nameOrObj ] ){
320 if( !css ) css = this._css = {};
321 name = XDomStyle.camelize( nameOrObj );
323 node = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;
324 if( css[ name ] === v ) return this;
328 node.style[ name ] = ''; // val
330 this._cssText = XDomStyle.objToCssText( css );
331 if( !this._cssText ){
332 delete this._cssText;
333 delete this._styleText;
334 node && node.removeAttribute( 'style' );
339 node.style[ name ] = v; // val
342 this._cssText = [ this._cssText, this._cssText ? ';' : '', XDomStyle.uncamelize( nameOrObj ), ':', v ].join( '' );
346 this._cssText = XDomStyle.objToCssText( css );
348 this._styleText = ' style="' + this._cssText + '"';
353 if( 1 < args.length && XDomStyle.UNIT[ nameOrObj ] ){ // unit
355 return XDomStyle.getValue( this, args[ 1 ], name );
357 // 集計 border, padding, margin, backgroundPosition, clip
358 // border で正確なデータを返せない時は、null を返す
359 return css[ XDomStyle.camelize( nameOrObj ) ];
362 X.Dom.Node.prototype.cssText = function( v ){
363 var camelize, obj, i, l, attr, name;
364 if( X.Type.isString( v ) ){
365 camelize = X.Dom.Style.camelize;
369 for( i = 0, l = v.length; i < l; ++i ){
370 attr = v[ i ].split( ':' );
371 name = camelize( attr[ 0 ] );
372 name && ( obj[ name ] = attr[ 1 ] || true );
374 return this.css( obj );
376 return this._cssText;
379 X.Dom.Node.prototype._getCharSize =
380 document.defaultView && document.defaultView.getComputedStyle ?
382 document.defaultView.getComputedStyle( this._rawNode, null );
384 X.UA.IE && 5 <= X.UA.IE ?
386 //this._rawNode.currentStyle;
388 document.removeChild ?
396 X.Dom.listenOnce( X.Dom.Event.DOM_PRE_INIT, function(){
397 var testStyle = X.Dom._view;
399 X.Dom.Style.VENDER_PREFIX = (function(){
401 vendors = ',webkit,Webkit,Moz,moz,ms,Ms,O,o,khtml,Khtml'.split( ',' ),
403 'opacity,boxSizing,' +
404 'transform,transformOrigin,perspective,' +
405 'transisiton,transitionDelay,transitionProperty,transitionDuration,transitionTimingFunction,' +
406 'userSelect,touchAction,touchCallout,contentZooming,userDrag,tapHighlightColor'.split( ',' ),
407 vendor, i, search, prop;
409 function findVenderPrefix( prop ){
410 var v, i = vendors.length;
414 if( testStyle[ v + prop ] !== undefined ){
421 for( i = searches.length; i; ){
422 search = searches[ --i ];
423 prop = findVenderPrefix( search );
424 if( search === 'transform' ) ret.transVender = vendor;
425 if( prop ) ret[ search ] = prop;
430 X.Dom.Style.SPECIAL_FIX_PROP =
432 X.UA.IE && X.UA.IE < 9 ?
435 opacity : 2//, uinode ChromeNode で行う
438 //backgroundImage : 5
441 X.UA.IE && 9 <= X.UA.IE && X.UA.IE < 10 ?
447 backgroundPositionX : testStyle.backgroundPositionX === undefined ? 3 : 0,
448 backgroundPosiitonY : testStyle.backgroundPositionX === undefined ? 3 : 0,
449 clipTop : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 3 : 0,
450 clipBottom : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 4 : 0,
451 clipLeft : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 5 : 0,
452 clipRight : testStyle.clipTop === undefined && testStyle[ 'clip-top' ] === undefined ? 6 : 0
456 X.Dom.listenOnce( X.Dom.Event.DOM_INIT, function(){
457 var xnode = Node._systemNode,
458 output = X.Dom.Style._UNIT_RATIO = {},
459 list = 'em,cm,mm,in,pt,pc'.split( ',' ),
462 for( i = list.length; i; ){
464 output[ unit ] = xnode.css( 'width', 100 + unit ).width() / 100;
467 output = X.Dom.Style._FONT_SIZE_RATIO = {},
468 list = 'xx-large,x-large,large,larger,medium,small,smaller,x-small,xx-small'.split( ',' );
469 base = xnode.css( 'lineHeight', 1 ).text( 'X' ).height();
471 for( i = list.length; i; ){
473 output[ size ] = xnode.css( 'fontSize', size ).height() / base;
476 xnode.empty().cssText( '' );