OSDN Git Service

Version 0.6.215, bug fixes X.Net.Image & X.HTMLAudio.
[pettanr/clientJs.git] / 0.6.x / js / 02_dom / 06_XNodeCSS.js
index 9711a5e..77bb067 100644 (file)
@@ -190,7 +190,7 @@ function X_Node_CSS_parseColor( x ){
        var rgb, r, g, b;
        
        if( X_Type_isNumber( x ) ){
-               return ( 0x0 <= x && x <= 0xFFFFFF ) ? x : undefined;
+               return ( 0x0 <= x && x <= 0xFFFFFF ) ? x : NaN;
        } else
        if( !X_Type_isString( x ) ) return;
        
@@ -239,14 +239,14 @@ function X_Node_CSS_parseColor( x ){
                        b *= 2.55;
                };
        } else {
-               return undefined;
+               return NaN;
        };
-       return isFinite( r + b + g ) ? ( r << 16 ) + ( g << 8 ) + b : undefined;
+       return X_Type_isFinite( r + b + g ) ? ( r << 16 ) + ( g << 8 ) + b : NaN;
 };
 
 function X_Node_CSS_objToCssText( that, skipFilter ){
        var obj   = that[ '_css' ],
-               plain = X_EMPTY_OBJECT,
+               //plain = X_EMPTY_OBJECT,
                css   = [],
                n     = -1,
                p, v, specialFix, filterFix;
@@ -260,7 +260,7 @@ function X_Node_CSS_objToCssText( that, skipFilter ){
        
        for( p in obj ){
                // object の拡張に備えて plain なオブジェクトを用意し、そのメンバーと一致するものは処理の対象外。
-               if( plain[ p ] ) continue;
+               //if( plain[ p ] ) continue;
                        
                v = obj[ p ];
                
@@ -277,8 +277,11 @@ function X_Node_CSS_objToCssText( that, skipFilter ){
        };
        
        if( filterFix ){
-               v = X_Node_CSS_objToIEFilterText( that, filterFix );
-               if( v ) css[ ++n ] = 'filter:' + v;
+               v = X_Node_CSS_objToIEFilterText( that, filterFix, css );
+               n = css.length; /* css が変更されている場合あり */
+               if( v ){
+                       css[ ++n ] = 'filter:' + v;
+               };
                skipFilter = skipFilter && v;
        } else {
                skipFilter = false;
@@ -287,6 +290,7 @@ function X_Node_CSS_objToCssText( that, skipFilter ){
        if( 0 <= n ){
                // cssText には完全なものを控えるが、戻すのは filter を抜いたもの
                that[ '_cssText' ] = css.join( ';' );
+               //console.log( that[ '_cssText' ] );
                if( skipFilter ){
                        --css.length;
                        return css.join( ';' );
@@ -299,12 +303,13 @@ function X_Node_CSS_objToCssText( that, skipFilter ){
 
 var
 X_Node_CSS_FILTER_FIX_PROPS =
-       X_UA[ 'ActiveX' ] && X_UA[ 'IE' ] < 9 && !X_UA[ 'MacIE' ] ?
+       X_UA[ 'ActiveX' ] && X_UA[ 'IE' ] < 9 ?
                {
-                       'opacity'    : 2,
-                       'boxShadow'  : 3,
-                       'textShadow' : 4,
-                       'transform'  : 5
+                       'opacity'     : 2,
+                       'boxShadow'   : 3,
+                       'textShadow'  : 4,
+                       'transform'   : 5,
+                       'dxtransform' : 7 // X.NodeAnime で使用
                } :
        X_UA[ 'ActiveX' ] && X_UA[ 'IE9' ] ? // == 9
                {
@@ -312,15 +317,16 @@ X_Node_CSS_FILTER_FIX_PROPS =
                } :
                null;
 
-function X_Node_CSS_objToIEFilterText( that, opt_css ){
+function X_Node_CSS_objToIEFilterText( that, opt_css, opt_cssList ){
        var obj     = opt_css || that[ '_css' ],
                test    = X_Node_CSS_FILTER_FIX_PROPS,
                filters = [],
                n       = -1,
-               p, id, v, num, ary, params, i, l, dir,
-               afterUpdate, impossible;
+               p, id, v, num, vu, u, _v, ary, params, i, l, dir,
+               afterUpdate, impossible, color;
+
        for( p in obj ){
-               if( X_EMPTY_OBJECT[ p ] ) continue;
+               //if( X_EMPTY_OBJECT[ p ] ) continue;
                
                if( !( id = test[ p ] ) ) continue;
                v = obj[ p ];
@@ -330,7 +336,11 @@ function X_Node_CSS_objToIEFilterText( that, opt_css ){
                                filters[ ++n ] = v;
                                break;
                        case 2 : //'opacity' :
-                               filters[ ++n ] = 'alpha(opacity=' + ( v * 100 | 0 ) +')';
+                               if( v === 0 ){
+                                       console.log( '@opacity:0 ' + !!opt_cssList );
+                                       opt_cssList && ( opt_cssList[ opt_cssList.length ] = 'visibility:hidden' );
+                               } else
+                               if( v < 1 ) filters[ ++n ] = 'alpha(opacity=' + ( v * 100 | 0 ) +')';
                                break;
                        case 3 : //'boxShadow' :
                                // TODO カンマ区切りの複数指定
@@ -396,25 +406,131 @@ function X_Node_CSS_objToIEFilterText( that, opt_css ){
                                        X_ViewPort[ 'listenOnce' ]( X_EVENT_AFTER_UPDATE, that, X_Node_CSS_onAfterUpdateForIEFilterFix );
                                        break;
                                };
-                               dir = Math.atan2( params[ 1 ] + params[ 3 ], params[ 0 ] + params[ 3 ] ) * 180 / Math.PI + 90;
-                               dir += dir < 0 ? 360 : 0;
+                               dir = X_Node_CSS_ieMathRangeFix( Math.atan2( params[ 1 ] + params[ 3 ], params[ 0 ] + params[ 3 ] ) * 180 / Math.PI + 90 );
                                filters[ ++n ] = 'shadow(color=' + color + ',strength=' + params[ 3 ] + ',direction=' + ( dir | 0 ) + ')';
                                break;
                        case 4 : //'textShadow' :
                                //text-shadow: 5px 5px 2px blue; 水平方向の距離 垂直方向の距離 影のぼかし半径 影の色 none
                                //glow(Color=yellow,Strength=10);
-                               //どうやらCSSのbackgroundプロパティと同時に使えないようです。 s
+                               //どうやらCSSのbackgroundプロパティと同時に使えないようです。 
                                break;
                        case 6 : //'backgroundImage' :
                                //
-                       
+                               break;
+
                        case 5 : // transform scale, matrix
-                               
+                               break;
+                       case 7 : // dxtransform
+                               that[ '_flags' ] |= X_NodeFlags_IE_FILTER_FIX_AFTER;
+                               break;
                };
        };
-       return filters.join( ' ' );
+       return filters.join( ' ' );//n !== -1 ? filters.join( ' ' ) : '';
 };
 
+
+       //0 ~ 360の範囲に収める.
+       function X_Node_CSS_ieMathRangeFix( a ){
+               a %= 360;
+               return a < 0 ? 360 + a : a;
+       };
+
+/*
+ * http://p2b.jp/200912-CSS3-Transform-for-IE8
+ * http://rtilabs.rti-giken.jp/files/2011_09_16/rotate.html
+ */
+       function X_Node_CSS_IETransform( elm, params ){
+               var PI_180 = Math.PI / 180,
+
+                       rotate = X_Node_CSS_ieMathRangeFix( params[ 2 ] ),//回転
+                       radian = rotate * PI_180,
+                       cosX   = Math.cos( radian ),
+                       sinY   = Math.sin( radian ),
+                       
+                       skewX  = X_Node_CSS_ieMathRangeFix( params[ 3 ] ), //skew
+                       skewY  = X_Node_CSS_ieMathRangeFix( params[ 4 ] ),
+                       
+                       _skX   = Math.tan( skewX * PI_180 ),
+                       _skY   = Math.tan( skewY * PI_180 ),
+                       
+                       scaleX = params[ 5 ], //拡大
+                       scaleY = params[ 6 ],
+                       
+                       m11    = cosX * scaleX,
+                       m12    = ( -sinY + _skX ) * scaleX,
+                       m21    = (  sinY + _skY ) * scaleY,
+                       m22    = cosX * scaleY,
+
+                       //absolute時には軸を補正してあげないとだめだ。
+                       //ブラウザとして軸がずれている。
+                       //計算式元ネタ http://p2b.jp/200912-CSS3-Transform-for-IE8
+       
+                       //offset*系のサイズは回転によって生じたゆがみも考慮されるらしい。
+       
+                       //拡大縮小も同じ.
+                       //this.get(0).style.width や height には拡縮の影響を受けない元の数字が入っている
+                       ow = elm.offsetWidth,
+                       oh = elm.offsetHeight,
+       
+                       absCosX = Math.abs( cosX ),
+                       absSinY = Math.abs( sinY ),
+       
+                               //回転の補正
+                       dx = ( ow - ( ow * absCosX + oh * absSinY ) ) / 2
+                               //skewの補正(rotate しながらskew すると補正がおかしくなります。 これがわからない)
+                                - ow / 2 * _skX
+                               //拡大の補正
+                                - ( ( ow * scaleX - ow ) / 2 | 0 )
+                               // x
+                                + params[ 0 ],
+                       dy = ( oh - ( ow * absSinY + oh * absCosX ) ) / 2
+                               //skewの補正(
+                                - oh / 2 * _skY
+                               //拡大の補正
+                                - ( ( oh * scaleY - oh ) / 2 | 0 )
+                               // y
+                                + params[ 1 ];
+
+               //console.log( ow +  ' ' + oh )
+               elm.style[ params[ 7 ] ] = dx + 'px'; // left or right
+               elm.style[ params[ 8 ] ] = dy + 'px'; // top  or bottom
+               
+               //フィルターで回転と拡大縮小を加えます。
+               return 'progid:DXImageTransform.Microsoft.Matrix(' +
+                                                               // 'Dx='  + dx +
+                                                               //',Dy='  + dy +
+                                                                'M11=' + m11 + 
+                                                               ',M12=' + m12 + 
+                                                               ',M21=' + m21 + 
+                                                               ',M22=' + m22 + 
+                                                               ',FilterType="bilinear",sizingMethod="auto expand")';
+       };
+
+function X_Node_CSS_onAfterUpdateIEFilterFix( that ){
+       var PI_180 = Math.PI / 180,
+               test   = X_Node_CSS_FILTER_FIX_PROPS,
+               css    = that[ '_css' ],
+               elm    = that[ '_rawObject' ],
+               filter = elm.style.filter || '',
+               origin = filter,
+               p, v, plus, id;
+
+       for( p in css ){
+               if( !( id = test[ p ] ) ) continue;
+               plus = 0;
+               switch( id ){
+                       case 7 : // dxtransform
+                               plus = X_Node_CSS_IETransform( elm, css[ p ] );
+                               break;
+                       default :
+                               continue;
+               };
+               if( plus ) filter += ( filter ? ' ' : '' ) + plus;
+       };
+       if( filter !== origin ) elm.style.filter = filter;
+};
+
+
 function X_Node_CSS_onAfterUpdateForIEFilterFix(){
        if( this[ '_flags' ] & X_NodeFlags_IN_TREE ){ // 要素があり、要素がツリーに属している
                this[ '_flags' ] |= X_NodeFlags_DIRTY_IE_FILTER;
@@ -526,11 +642,11 @@ function X_Node_css( nameOrObj /* value */ ){
 // setter:object
        if( X_Type_isObject( nameOrObj ) ){
                if( !css ) css = this[ '_css' ] = {};
-               plain    = X_EMPTY_OBJECT;
+               //plain    = X_EMPTY_OBJECT;
                camelize = X_Node_CSS_camelize;
                flags    = this[ '_flags' ];
                for( p in nameOrObj ){
-                       if( plain[ p ] ) continue;
+                       //if( plain[ p ] ) continue;
                        name = camelize( p );
                        v    = nameOrObj[ p ];
                        if( css[ name ] === v ) continue;
@@ -584,6 +700,7 @@ function X_Node_CSS_setStyle( css, flags, name, newValue ){
                        return flags;
                        
                case 'opacity' :
+                       flags |= X_NodeFlags_IE8_OPACITY_FIX;
                        // すでに visibility:hidden で invisible
                        if( flags & X_NodeFlags_STYLE_IS_INVISIBLE && css[ 'visibility' ] === 'hidden' ) return flags;
                        newValue == 0 ? // 0 or "0"
@@ -639,7 +756,7 @@ function X_Node_CSS_setStyle( css, flags, name, newValue ){
 function X_Node_cssText( v ){
        var obj, i, l, attr, name;
        
-       if( v === this[ '_cssText' ] && ( this[ '_flags' ] & X_NodeFlags_OLD_CSSTEXT ) === 0 ){
+       if( v === this[ '_cssText' ] && ( ( this[ '_flags' ] & X_NodeFlags_OLD_CSSTEXT ) === 0 ) ){
                return this;
        };      
        
@@ -667,7 +784,7 @@ function X_Node_cssText( v ){
 };
 
 /*
- * ここでは HTMLElement のチ1ェックは行わない!
+ * ここでは HTMLElement のチ1ェックは行わない! <- 行う!
  * TODO
  * body に css attr がセットされた場合には X_ViewPort_baseFontSize をクリア
  * class, id, attr(<font size><basefont>) の変更があった場合は、変更の適用の後、charSize を取得
@@ -681,12 +798,13 @@ X_Node_CSS_getCharSize =
                        X_Node_updateTimerID && X_Node_startUpdate();
                        if( that === X_Node_body && X_ViewPort_baseFontSize ) return X_ViewPort_baseFontSize;
                        if( that[ '_fontSize' ] ) return that[ '_fontSize' ];
-                       return that[ '_fontSize' ] = parseFloat( X_Node_CSS_getComputedStyle( that[ '_rawObject' ], null ).fontSize );
+                       return that[ '_fontSize' ] = that[ '_rawObject' ] ? parseFloat( X_Node_CSS_getComputedStyle( that[ '_rawObject' ], null ).fontSize ) : 0;
                }) :
 
        5 <= X_UA[ 'IE' ] ?
                (function( that ){
                        var font, vu, v, u, _v;
+                       
                        X_Node_updateTimerID && X_Node_startUpdate();
                        if( that === X_Node_body && X_ViewPort_baseFontSize ) return X_ViewPort_baseFontSize;
                        if( that[ '_fontSize' ] ) return that[ '_fontSize' ];
@@ -731,11 +849,12 @@ X_Node_CSS_getCharSize =
                }) :
        X_UA_DOM.IE4 ?
                (function( that ){
-                       var font, vu, v, u, _v;
+                       var font, vu, v, u, _v, elm;
+                       
                        X_Node_updateTimerID && X_Node_startUpdate();
                        if( that === X_Node_body && X_ViewPort_baseFontSize ) return X_ViewPort_baseFontSize;
                        if( that[ '_fontSize' ] ) return that[ '_fontSize' ];
-                       
+
                        if( that[ '_css' ] && ( font = that[ '_css' ].fontSize ) ){
                                vu = X_Node_CSS__splitValueAndUnit( font );
                                v  = vu[ 0 ];
@@ -747,7 +866,7 @@ X_Node_CSS_getCharSize =
                                        if( _v = X_Node_CSS__UNIT_RATIO[ u ] ) return that[ '_fontSize' ] = v / _v;
                                };
                        } else {
-                               // 要素を生成して測定!
+                               // TODO 要素を生成して測定! ではなくて elm.style.fontSize が使えそう
                                ( that[ '_rawObject' ] || X_Node__ie4getRawNode( that ) ).insertAdjacentHTML( 'BeforeEnd', '<div id="ie4charsize" style="position:absolute;top:0;left:0;visivility:hidden;line-height:1;height:1em;">X</div>' );
                                elm = document.all[ 'ie4charsize' ];
                                v = elm.offsetHeight;
@@ -789,11 +908,14 @@ var X_Node_CSS_Support = {},
  * @namespace X.CSS
  */
 X[ 'CSS' ] = {
-       
+       /**
+        * @alias X.CSS.VENDER_PREFIX
+        */
        'VENDER_PREFIX' : X_Node_CSS_VENDER_PREFIX,
-       // iscroll で使用
-       'uncamelize'    : X_Node_CSS_uncamelize,
-       
+
+       /**
+        * @alias X.CSS.Support
+        */
        'Support'       : X_Node_CSS_Support
 };
 
@@ -825,7 +947,7 @@ X[ 'CSS' ] = {
                        for( j = vendors.length; j; ){
                                v = vendors[ --j ];
                                if( testStyle[ v + prop ] !== undefined ){
-                                       if( v === 'ms' ) v = 'Ms';// for ie9
+                                       if( v === 'ms'/* && !( 10 <= X_UA[ 'IEHost' ] )*/ ) v = 'Ms';// for ie9, 但し ie11 のieには不要
                                        if( v === 'o' ) v = 'O';//for opera12
                                        X_Node_CSS_VENDER_PREFIX[ search ] = v + prop;
                                        break;
@@ -837,41 +959,62 @@ X[ 'CSS' ] = {
        };
        
        testStyle.cssText = 'background:rgba(0,0,0,0.5);border-color:transparent';
+/**
+ * 色指定に rgba() が使用できるか?
+ * @alias X.CSS.Support.rgba
+ * @type {boolean}
+ */
        X_Node_CSS_Support[ 'rgba' ] = !!testStyle[ 'background' ];
+       
+/**
+ * 色指定に transparent が使用できるか?
+ * @alias X.CSS.Support.transparent
+ * @type {boolean}
+ */
        X_Node_CSS_Support[ 'transparent' ] = !!testStyle[ 'borderColor' ];
        // TODO border による三角形の可否
        // 2:完全、 1:透過に非対応(IE7-) 0:borderの描画が非標準で三角形が作れない
-       
-               /*
-                * chrome 1+, ff3.5(1.9.1), ie9+, opera10.5+, Safari3+(522)
-                */
+
        if( prop = X_Node_CSS_VENDER_PREFIX[ 'boxShadow' ] ){
                
                testStyle.cssText = X_Node_CSS_uncamelize( prop ) + ':0 0';
+               
+               /**
+                * boxShadow が使用できるか?
+                * chrome 1+, ff3.5(1.9.1), ie9+, opera10.5+, Safari3+(522)
+                * @alias X.CSS.Support.boxShadow
+                * @type {boolean}
+                */
                X_Node_CSS_Support[ 'boxShadow' ] = !!testStyle[ prop ];
 
-               /*
+               testStyle.cssText = X_Node_CSS_uncamelize( prop ) + ':0 0, 0 0';
+               
+               /**
+                * boxShadow の複数指定が使用できるか?<br>
                 * chrome 4+, ff3.5(1.9.1), ie9+, opera10.5+, Safari5+(533)
+                * @alias X.CSS.Support.boxShadowMulti
+                * @type {boolean}
                 */
-               testStyle.cssText = X_Node_CSS_uncamelize( prop ) + ':0 0, 0 0';
                X_Node_CSS_Support[ 'boxShadowMulti' ] = !!testStyle[ prop ];
                
-               /*
-                * https://developer.mozilla.org/ja/docs/Web/CSS/box-shadow
-                * この値を用いる場合には、spread-radius を省略出来ません。box-shadow が効かないケースに遭遇した時はこの事を思い出して下さい。
-                * chrome 4+, ff3.5(1.9.1), ie9+, opera10.5+, Safari5+(533)
+               testStyle.cssText = X_Node_CSS_uncamelize( prop ) + ':0 0 inset';
+               
+               /**
+                * https://developer.mozilla.org/ja/docs/Web/CSS/box-shadow<br>
+                * この値を用いる場合には、spread-radius を省略出来ません。box-shadow が効かないケースに遭遇した時はこの事を思い出して下さい。<br>
+                * chrome 4+, ff3.5(1.9.1), ie9+, opera10.5+, Safari5+(533)<br>
                 * 
-                * http://unformedbuilding.com/articles/considerations-when-using-the-box-shadow/
-                *  box-shadow:inset と border-radius を指定しているときの Google Chrome の表示
-                *  このバグは Windows と Linux で発生するようです。
-                *  Windows 版 Chrome 10.0.648.127 で修正されているのを確認しました。
+                * http://unformedbuilding.com/articles/considerations-when-using-the-box-shadow/<br>
+                *  box-shadow:inset と border-radius を指定しているときの Google Chrome の表示<br>
+                *  このバグは Windows と Linux で発生するようです。<br>
+                *  Windows 版 Chrome 10.0.648.127 で修正されているのを確認しました。<br>
+                * @alias X.CSS.Support.boxShadowInset
+                * @type {boolean}
                 */
-               testStyle.cssText = X_Node_CSS_uncamelize( prop ) + ':0 0 inset';
                X_Node_CSS_Support[ 'boxShadowInset' ] = testStyle[ prop ] && testStyle[ prop ].indexOf( 'inset' ) !== -1;
 
        };
 
-       
        testStyle.cssText = temp;
 
 })();