OSDN Git Service

Version 0.6.195, add opacity-fix for IE8.
[pettanr/clientJs.git] / 0.6.x / js / 02_dom / 20_XNode.js
index e7d85ec..cc826b1 100644 (file)
@@ -9,7 +9,6 @@
 var    Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](
        'X.Node',
        X_Class.POOL_OBJECT,
-       
        {
                /**
                 * 要素に振られるユニークID
@@ -152,6 +151,7 @@ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](
         * TODO Node の継承ができない!
         */
                'Constructor' : function( v ){
+                       // TODO uid = X_Node_CHASHE.indexOf( null ), uid === -1 ? X_Node_CHASHE.length : uid;
                        var uid = X_Node_CHASHE.length,
                                css, xnodes, xnode, parent;
                        
@@ -383,7 +383,7 @@ function X_Node_getXNode( v ){
                case X_NodeType_RAW_TEXT :
                        if( v[ 'UID' ] ) return X_Node_CHASHE[ v[ 'UID' ] ];
                        for( chashe = X_Node_CHASHE, i = chashe.length; i; ){
-                               if( ( xnode = X_Node_CHASHE[ --i ] ) && ( xnode[ '_rawObject' ] === v ) ) return xnode;
+                               if( ( xnode = chashe[ --i ] ) && ( xnode[ '_rawObject' ] === v ) ) return xnode;
                        };
        };
 };
@@ -394,11 +394,10 @@ function X_Node_getRoot( xnode ){
 };
 
 
-
+// TODO document.all[ uid ] -> document[ uid ] 
 var X_Node__ie4getRawNode = X_UA_DOM.IE4 && function ( that ){
                return that[ '_rawObject' ] ||
-                       ( that[ '_rawObject' ] = document.all[ 'ie4uid' + that[ '_uid' ] ] ) ||
-                       ( that[ '_id' ] && ( that[ '_rawObject' ] = document.all[ that[ '_id' ] ] ) );
+                       ( that[ '_rawObject' ] = document.all[ 'ie4uid' + that[ '_uid' ] ] || that[ '_id' ] && document.all[ that[ '_id' ] ] );
        };
 
 
@@ -562,7 +561,7 @@ function X_Node_append( v ){
                        // 親の xnodes から v を消す
                        v.parent && v[ 'remove' ]();
                        // IE4 でテキストノードの追加、FIXED 済でない場合、親に要素の追加を通知
-                       if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( this[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) this[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
+                       if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( ( this[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ) this[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
                        break;
                default :
                        return this;
@@ -638,7 +637,7 @@ function X_Node_appendAt( start, v ){
                                v[ 'remove' ]();
                        };
                        // IE4 でテキストノードの追加、FIXED 済でない場合、親に要素の追加を通知
-                       if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( this[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) this[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
+                       if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( ( this[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ) this[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
                        break;
                default :
                        return this;
@@ -768,10 +767,11 @@ function X_Node_swap( v ){
 };
 
 /**
- * 要素を抜く。
+ * 要素を親要素から抜く。jQuery の remove と異なり、インスタンスは破壊(kill)されず、再び別の親に挿入等できる
  * @alias Node.prototype.remove
  * @return {Node} 自身。チェインメソッド
  * @example node.remove();
+ * parent.append( node ); 新しい親に追加できる
  */
 function X_Node_remove(){
        var parent = this.parent,
@@ -791,7 +791,7 @@ function X_Node_remove(){
                                X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = this;
                                X_Node_reserveUpdate();                 
                        } else
-                       if( !this[ '_tag' ] && ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ){
+                       if( !this[ '_tag' ] && ( ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ){
                                parent[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
                        };
                } else {
@@ -821,7 +821,9 @@ function X_Node_remove(){
  */
 function X_Node_empty(){
        var xnodes = this[ '_xnodes' ], i;
+       
        if( xnodes && ( i = xnodes.length ) ){
+               delete this[ '_xnodes' ];
                for( ; i; ){
                        xnodes[ --i ][ 'kill' ]();
                };
@@ -836,31 +838,33 @@ function X_Node_onKill( that ){
        
        if( ( that[ '_flags' ] & X_NodeFlags_EXIST ) === 0 ) return;
        
-       parent && parent[ '_xnodes' ].splice( parent[ '_xnodes' ].indexOf( that ), 1 );
+       parent && parent[ '_xnodes' ] && parent[ '_xnodes' ].splice( parent[ '_xnodes' ].indexOf( that ), 1 );
 
        elm = that[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( that );
-       // elm && that[ '_listeners' ] && X_EventDispatcher_unlistenAll( that ); // イベントの退避
 
        if( xnodes && ( i = xnodes.length ) ){
+               delete that[ '_xnodes' ];
                for( ; i; ){
                        xnodes[ --i ][ 'kill' ]();
                };
+               xnodes.length = 0;
        };
 
-       delete X_Node_CHASHE[ that[ '_uid' ] ];
+       X_Node_CHASHE[ that[ '_uid' ] ] = null; // array に対して delete X_Node_CHASHE[ uid ] はまずい!
+       
 // remove _xnodes
        if( X_UA_DOM.IE4 ){
                if( elm ){
                        X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = elm;
                        X_Node_reserveUpdate();                 
                } else
-               if( !that[ '_tag' ] && ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ){
+               if( !that[ '_tag' ] && ( ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ){
                        parent[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
                };
        } else {
                if( elm && elm.parentNode && elm.parentNode.tagName ){
                        X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = elm;
-                       X_Node_reserveUpdate();         
+                       X_Node_reserveUpdate();
                };
        };
 };
@@ -1095,7 +1099,12 @@ function X_Node_html( html ){
        // setter
        if( html !== undefined ){ // String 以外に Number や false null なども許可
                if( !this[ '_tag' ] ) return this[ 'text' ]( html );
-               return html ? this[ 'empty' ]()[ 'append' ].apply( this, X_HtmlParser_parse( html, true ) ) : this[ 'empty' ]();
+               
+               this[ 'empty' ]();
+               if( html ){
+                       X_Node_append.apply( this, X_HtmlParser_parse( html, true ) );
+               };
+               return this;
        };
        
        // getter
@@ -1205,7 +1214,7 @@ function X_Node_call( name /*, opt_args... */ ){
                case 'treeIsDirty' :
                        return !!X_Node_updateTimerID;
                case 'fontSize' :
-                       return X_Node_CSS_getCharSize( this );
+                       return this.parent ? X_Node_CSS_getCharSize( this ) : 0;
                case 'inGPU' :
                        return !!( this[ '_flags' ] & ( X_NodeFlags_GPU_NOW | X_NodeFlags_GPU_RELEASE_RESERVED ) );
        };
@@ -1223,7 +1232,7 @@ function X_Node_call( name /*, opt_args... */ ){
        };
        
        if( name === 'inView' ){
-               body   = document.body;
+               body   = X_elmBody;
                child  = raw;
                visibleX = visibleY = visibleW = visibleH = 0;
                while( child !== body ){
@@ -1372,10 +1381,10 @@ function X_Node_startUpdate( time ){
        };
        
        if( X_Node_html[ '_flags' ] & X_Node_BitMask_IS_DIRTY ){
-               X_Node__commitUpdate( X_Node_html, X_Node_html[ '_rawObject' ].parentNode, null, X_Node_html[ '_flags' ] );
+               X_Node__commitUpdate( X_Node_html, X_Node_html[ '_rawObject' ].parentNode, null, X_Node_html[ '_flags' ], 1 );
        } else {
-               X_Node__commitUpdate( X_Node_head, X_Node_head[ '_rawObject' ].parentNode, null, X_Node_head[ '_flags' ] );
-               X_Node__commitUpdate( X_Node_body, X_Node_body[ '_rawObject' ].parentNode, null, X_Node_body[ '_flags' ] );
+               X_Node__commitUpdate( X_Node_head, X_Node_head[ '_rawObject' ].parentNode, null, X_Node_head[ '_flags' ], 1 );
+               X_Node__commitUpdate( X_Node_body, X_Node_body[ '_rawObject' ].parentNode, null, X_Node_body[ '_flags' ], 1 );
        };
        
        if( X_Node_updateReservedByReleaseGPU ){
@@ -1408,13 +1417,13 @@ function X_Node_startUpdate( time ){
  */
 var X_Node__commitUpdate =
        X_UA_DOM.W3C ?
-               ( function( that, parentElement, nextElement, accumulatedFlags ){
+               ( function( that, parentElement, nextElement, accumulatedFlags, ie8opacity ){
                        var elm = that[ '_rawObject' ],
                                created, xnodes, l, next;
 
                        // 1. GPU 一切の更新をスキップ
                        if( that[ '_flags' ] & X_NodeFlags_GPU_NOW ){
-                               console.log( '更新のskip ' + !!( that[ '_flags' ] & X_Node_BitMask_IS_DIRTY ) );
+                               //console.log( '更新のskip ' + !!( that[ '_flags' ] & X_Node_BitMask_IS_DIRTY ) );
                                that[ '_flags' ] & X_Node_BitMask_IS_DIRTY && X_Node__updateRawNode( that, elm );
                                return elm;
                        };
@@ -1423,7 +1432,6 @@ var X_Node__commitUpdate =
                        if( that[ '_flags' ] & X_NodeFlags_GPU_RELEASE_RESERVED ){
                                // console.log( 'GPU 解放 ' );
                                //X_Node_updateReservedByReleaseGPU = true;
-                               //X_Node__updateRawNode( that, elm );
                                that[ '_flags' ] &= X_Node_BitMask_RESET_GPU;
                                //return elm;// TODO もしかしたらこのタイミングで更新できるかも。
                        };
@@ -1452,7 +1460,7 @@ var X_Node__commitUpdate =
                        accumulatedFlags |= that[ '_flags' ];
                        
                        if( that[ '_flags' ] & X_NodeFlags_IE5_DISPLAY_NONE_FIX ){
-                               if( accumulatedFlags & ( X_NodeFlags_DIRTY_POSITION | X_NodeFlags_DIRTY_ID | X_NodeFlags_DIRTY_CLASSNAME ) === 0 ){
+                               if( ( accumulatedFlags & ( X_NodeFlags_DIRTY_POSITION | X_NodeFlags_DIRTY_ID | X_NodeFlags_DIRTY_CLASSNAME ) ) === 0 ){
                                        return nextElement;
                                };
                        };
@@ -1461,7 +1469,7 @@ var X_Node__commitUpdate =
                        if( !elm ){
                                if( !that[ '_tag' ] ){
                                        that[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
-                                       that[ '_rawObject' ] = elm = document.createTextNode( X_String_chrReferanceTo( that[ '_text' ] ) );
+                                       elm = document.createTextNode( X_String_chrReferanceTo( that[ '_text' ] ) );
                                        if( !X_UA[ 'IE' ] ){
                                                elm[ 'UID' ] = that[ '_uid' ];
                                        };
@@ -1469,7 +1477,7 @@ var X_Node__commitUpdate =
                                if( X_Node_strictElmCreation ){
                                        that[ '_flags' ] & X_NodeFlags_OLD_CSSTEXT && X_Node_CSS_objToCssText( that, true ); // OLD_CSSTEXT ??
                
-                                       that[ '_rawObject' ] = elm =
+                                       elm =
                                                document.createElement( [
                                                        '<', that[ '_tag' ],
                                                                ' UID="', that[ '_uid' ], '"',
@@ -1478,14 +1486,17 @@ var X_Node__commitUpdate =
                                                                X_Node_Attr_objToAttrText( that, true ),
                                                                that[ '_cssText' ] ? ' style="' + that[ '_cssText' ] + '"' : '',
                                                        '>' ].join( '' ) );
+                               } else
+                               if( that[ '_flags' ] & X_NodeFlags_IS_SVG ){
+                                       elm = document.createElementNS( 'http://www.w3.org/2000/svg', that[ '_tag' ].toLowerCase() );
+                                       
+                                       // math http://www.w3.org/1998/Math/MathML
                                } else {
-                                       if( that[ '_flags' ] & X_NodeFlags_IS_SVG ){
-                                               that[ '_rawObject' ] = elm = document.createElementNS( 'http://www.w3.org/2000/svg', that[ '_tag' ].toLowerCase() );
-                                       } else {
-                                               that[ '_rawObject' ] = elm = document.createElement( that[ '_tag' ] );
-                                       };
+                                       elm = document.createElement( that[ '_tag' ] );
                                };
                                
+                               that[ '_rawObject' ] = elm;
+                               
                                // IE には要素追加のタイミングで起こるメモリリークがありここで追加
                                if( !X_Node_addTreeAfterChildren ){
                                        nextElement ?
@@ -1497,10 +1508,10 @@ var X_Node__commitUpdate =
                                        X_EventDispatcher_toggleAllEvents( that, true );// イベントの復帰                                
                                        that[ '_flags' ] |= X_NodeFlags_ACTUAL_LISTENING;
                                        
-                                       if( X_Node_documentFragment ){
+                                       //if( X_Node_documentFragment ){
                                                //( frg = X_Node_documentFragment ).appendChild( elm );
                                                // 連続する要素の差し替えの場合に有効
-                                       };
+                                       //};
 
                                        if( X_Node_strictElmCreation ){
                                                that[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
@@ -1533,15 +1544,17 @@ var X_Node__commitUpdate =
                                        parentElement.appendChild( elm );
                        };
                        
-                       if( that[ '_listeners' ] && ( that[ '_flags' ] & X_NodeFlags_ACTUAL_LISTENING ) === 0 ){
+                       if( that[ '_listeners' ] && ( ( that[ '_flags' ] & X_NodeFlags_ACTUAL_LISTENING ) === 0 ) ){
                                X_EventDispatcher_toggleAllEvents( that, true );// イベントの退避
                                that[ '_flags' ] |= X_NodeFlags_ACTUAL_LISTENING;
                        };
                        
+                       ie8opacity = ie8opacity * ( that[ '_css' ] && 0 <= that[ '_css' ].opacity ? that[ '_css' ].opacity : 1 );
+                       
                        // 8. 更新の適用
                        if( accumulatedFlags & X_Node_BitMask_IS_DIRTY ){
                                delete that[ '_fontSize' ];
-                               X_Node__updateRawNode( that, elm );
+                               X_Node__updateRawNode( that, elm, ie8opacity, accumulatedFlags );
                        };
 
                        // 9. ie5 only
@@ -1561,7 +1574,7 @@ var X_Node__commitUpdate =
                        // 10. 子要素の更新。
                        if( ( xnodes = that[ '_xnodes' ] ) && ( l = xnodes.length ) ) {
                                for( ; l; ){
-                                       next = X_Node__commitUpdate( xnodes[ --l ], elm, next, accumulatedFlags );
+                                       next = X_Node__commitUpdate( xnodes[ --l ], elm, next, accumulatedFlags, ie8opacity );
                                };
                        };
 
@@ -1676,8 +1689,8 @@ var X_Node__commitUpdate =
  */
 var X_Node__updateRawNode =
        X_UA_DOM.W3C ?
-               ( function( that, elm ){
-                       var attrs, rename, k, v;
+               ( function( that, elm, ie8opacity, accumulatedFlags ){
+                       var attrs, rename, k, v, memory, f;
 
                        // textNode
                        if( !that[ '_tag' ] ){
@@ -1751,6 +1764,20 @@ var X_Node__updateRawNode =
                                delete that[ '_newAttrs' ];
                        };
                        
+                       if( accumulatedFlags & X_NodeFlags_IE8_OPACITY_FIX ){
+                               memory = that[ '_css' ] && that[ '_css' ].opacity;
+                               if( f = true ){
+                                       if( !that[ '_css' ] ) that[ '_css' ] = {};
+                                       that[ '_css' ].opacity = ie8opacity;
+                                       if( that[ '_flags' ] & X_NodeFlags_DIRTY_CSS ){
+                                               that[ '_flags' ] |= X_NodeFlags_OLD_CSSTEXT;
+                                       } else
+                                       if( !( that[ '_flags' ] & X_NodeFlags_DIRTY_IE_FILTER ) ){
+                                               that[ '_flags' ] |= X_NodeFlags_DIRTY_IE_FILTER;
+                                       };
+                               };
+                       };
+                       
                        // style
                        if( that[ '_flags' ] & X_NodeFlags_DIRTY_CSS ){
                                if( that[ '_flags' ] & X_NodeFlags_OLD_CSSTEXT ? X_Node_CSS_objToCssText( that ) : that[ '_cssText' ] ){
@@ -1773,6 +1800,15 @@ var X_Node__updateRawNode =
                                };
                        };
                        
+                       if( f ){
+                               if( 0 <= memory ){
+                                       that[ '_css' ].opacity = memory;
+                               } else {
+                                       delete that[ '_css' ].opacity;
+                                       if( X_Object_isEmpty( that[ '_css' ] ) ) delete that[ '_css' ];
+                               };
+                       };
+                       
                        that[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
                }) :
        X_UA_DOM.IE4 ? 
@@ -1947,7 +1983,7 @@ var X_Node__actualRemove =
                                that[ '_listeners' ] && X_EventDispatcher_toggleAllEvents( that, false );// イベントの退避
                                that[ '_flags' ] &= ~X_NodeFlags_ACTUAL_LISTENING;
                        };
-                       
+
                        // ie5では filter の効いている要素をremove時に破棄して、再度append 時に新規生成する
                        // ちなみに elm.filters に触ると ie8 でなぜかカラム落ちが発生、、、
                        if( X_Node_displayNoneFixForIE5 ){
@@ -1967,7 +2003,7 @@ var X_Node__actualRemove =
                                                if( !that[ '_attrs' ] ) that[ '_attrs' ] = {};
                                                that[ '_attrs' ].selectedIndex = elm.selectedIndex;
                                        };
-                                       if( that[ '_tag' ] === 'INPUT' && that._attr && ( that._attr.type === 'checkbox' || that._attr.type === 'radio' ) && ( !that[ '_newAttrs' ] || !X_Object_inObject( 'checked', that[ '_newAttrs' ] ) ) ){
+                                       if( that[ '_tag' ] === 'INPUT' && that[ '_attrs' ] && ( that[ '_attrs' ].type === 'checkbox' || that[ '_attrs' ].type === 'radio' ) && ( !that[ '_newAttrs' ] || !X_Object_inObject( 'checked', that[ '_newAttrs' ] ) ) ){
                                                if( !that[ '_attrs' ] ) that[ '_attrs' ] = {};
                                                that[ '_attrs' ].checked = elm.checked;
                                        };
@@ -2010,7 +2046,7 @@ var X_Node__actualRemove =
                                if( !that[ '_attrs' ] ) that[ '_attrs' ] = {};
                                that[ '_attrs' ].selectedIndex = elm.selectedIndex;
                        };
-                       if( that[ '_tag' ] === 'INPUT' && that._attr && ( that._attr.type === 'checkbox' || that._attr.type === 'radio' ) && ( !that[ '_newAttrs' ] || !X_Object_inObject( 'checked', that[ '_newAttrs' ] ) ) ){
+                       if( that[ '_tag' ] === 'INPUT' && that[ '_attrs' ] && ( that[ '_attrs' ].type === 'checkbox' || that[ '_attrs' ].type === 'radio' ) && ( !that[ '_newAttrs' ] || !X_Object_inObject( 'checked', that[ '_newAttrs' ] ) ) ){
                                if( !that[ '_attrs' ] ) that[ '_attrs' ] = {};
                                that[ '_attrs' ].checked = elm.checked;
                        };