OSDN Git Service

Version 0.6.176, add X.Script.
[pettanr/clientJs.git] / 0.6.x / js / 02_dom / 20_XNode.js
index e0aa707..7fb2e40 100644 (file)
@@ -221,8 +221,6 @@ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](
                        };
                        this[ '_flags' ] |= X_NodeFlags_EXIST;
                        X_Node_CHASHE[ this[ '_uid' ] = uid ] = this;
-                       
-                       X_EventDispatcher_systemListen( this, X_EVENT_BEFORE_KILL_INSTANCE, X_Node_onBeforeKill );
                },
                
                'width'          : X_Node_width,
@@ -505,17 +503,26 @@ function X_Node_createTextAt( index, text ){
  */
 function X_Node_clone( opt_clone_children ){
        var xnode, xnodes, i, l;
+       
        if( this[ '_tag' ] ){
                X_Node_newByTag = true;
-               xnode = Node( this[ '_tag' ], X_Object_clone( this[ '_attrs' ] ), X_Object_clone( this[ '_css' ] ) )
+               xnode = Node( this[ '_tag' ], X_Object_copy( this[ '_attrs' ] ), X_Object_copy( this[ '_css' ] ) )
                        [ 'attr' ]( { 'id' : this[ '_id' ] } )
                        [ 'className' ]( this[ '_className' ] );
+               
+               if( this[ '_flags' ] & X_NodeFlags_IS_SVG ){
+                       xnode[ '_flags' ] |= X_NodeFlags_IS_SVG;
+               };
+               if( this[ '_flags' ] & X_NodeFlags_IS_VML ){
+                       xnode[ '_flags' ] |= X_NodeFlags_IS_VML;
+               };
+               
                if( opt_clone_children && ( xnodes = this[ '_xnodes' ] ) && ( l = xnodes.length ) ){
                        for( i = 0; i < l; ++i ){
                                xnode[ 'append' ]( xnodes[ i ][ 'clone' ]( true ) );
                        };
                };
-               return xnode;           
+               return xnode;
        };
        X_Node_newByText = true;
        return Node( this[ '_text' ] );
@@ -568,6 +575,12 @@ function X_Node_append( v ){
                v[ '_xnodes' ] && X_Node_toggleInTreeFlag( v[ '_xnodes' ], true );
                X_Node_reserveUpdate();
        };
+       if( this[ '_flags' ] & X_NodeFlags_IS_SVG ){
+               v[ '_flags' ] |= X_NodeFlags_IS_SVG;
+       };
+       if( this[ '_flags' ] & X_NodeFlags_IS_VML ){
+               v[ '_flags' ] |= X_NodeFlags_IS_VML;
+       };
        return this;
 };
 
@@ -638,6 +651,12 @@ function X_Node_appendAt( start, v ){
                v[ '_xnodes' ] && X_Node_toggleInTreeFlag( v[ '_xnodes' ], true );
                X_Node_reserveUpdate();
        };
+       if( this[ '_flags' ] & X_NodeFlags_IS_SVG ){
+               v[ '_flags' ] |= X_NodeFlags_IS_SVG;
+       };
+       if( this[ '_flags' ] & X_NodeFlags_IS_VML ){
+               v[ '_flags' ] |= X_NodeFlags_IS_VML;
+       };
        return this;
 };
 
@@ -768,8 +787,7 @@ function X_Node_remove(){
                this[ '_xnodes' ] && X_Node_toggleInTreeFlag( this[ '_xnodes' ], false );
 
                if( X_UA_DOM.IE4 ){
-                       elm = this[ '_rawObject' ] || X_Node__ie4getRawNode( this );
-                       if( elm ){
+                       if( elm = this[ '_rawObject' ] || X_Node__ie4getRawNode( this ) ){
                                X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = this;
                                X_Node_reserveUpdate();                 
                        } else
@@ -783,6 +801,14 @@ function X_Node_remove(){
                                X_Node_reserveUpdate();                 
                        };
                };
+       } else {
+               if( !X_UA_DOM.IE4 ){
+                       elm = this[ '_rawObject' ];
+                       if( elm && elm.parentNode && elm.parentNode.tagName ){
+                               X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = this;
+                               X_Node_reserveUpdate();                 
+                       };
+               };
        };
        return this;
 };
@@ -804,33 +830,44 @@ function X_Node_empty(){
        return this;
 };
 
-function X_Node_onBeforeKill( e ){
-       var xnodes = this[ '_xnodes' ], i, elm;
+function X_Node_onKill( that ){
+       var parent = that.parent,
+               xnodes = that[ '_xnodes' ], i, elm;
        
-       if( ( this[ '_flags' ] & X_NodeFlags_EXIST ) === 0 ) return X_Callback_NONE;
+       if( ( that[ '_flags' ] & X_NodeFlags_EXIST ) === 0 ) return;
        
-       elm = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );
-       elm && this[ '_listeners' ] && X_EventDispatcher_unlistenAll( this ); // イベントの退避
+       parent && 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 ) ){
                for( ; i; ){
-                       X_Node_onBeforeKill.call( xnodes[ --i ] );
+                       xnodes[ --i ][ 'kill' ]();
                };
        };
 
-       delete X_Node_CHASHE[ this[ '_uid' ] ];
-
-       if( e ){
-               this[ 'remove' ]();
-               if( X_Node_reserveRemoval[ X_Node_reserveRemoval.length - 1 ] === this ){
-                       this[ '_flags' ] &= ~X_NodeFlags_EXIST;
-                       return X_Callback_PREVENT_DEFAULT;              
-               };              
+       delete X_Node_CHASHE[ that[ '_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 ){
+                       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();         
+               };
        };
-       return X_Callback_NONE;
 };
 
 
+
+
 /**
  * 要素を子以下に持つか?調べる。
  * @alias Node.prototype.contains
@@ -1136,14 +1173,28 @@ function X_Node_text( text ){
        return this[ '_text' ];
 };
 
-/*
+/**
  * HTML要素に対して name の関数を実行しその戻り値を返す。関数に渡す引数も任意に設定できる。
+ * @alias Node.prototype.call
+ * @param {string} [name] 要素の関数名
+ * @return {*} 
+ * @example node.call( 'focus' );
  */
 function X_Node_call( name /*, opt_args... */ ){
-       var l = arguments.length - 1,
-               raw, func, args, params, i;
+       var args = arguments,
+               l    = args.length - 1,
+               v, raw, parent, body,
+               childX, childY, childW, childH,
+               parentW, parentH,
+               parentSX, parentSY, parentSW, parentSH,
+               visibleX, visibleY, visibleW, visibleH,
+               visiblePartX, visiblePartY, func, args, params, i;
 
        switch( name ){
+               case 'isSVG' :
+                       return !!( this[ '_flags' ] & X_NodeFlags_IS_SVG );
+               case 'isVML' :
+                       return !!( this[ '_flags' ] & X_NodeFlags_IS_VML );
                case 'nodeType' :
                        return this[ '_tag' ] ? 1 : 3;
                case 'outerHTML' :
@@ -1162,28 +1213,79 @@ function X_Node_call( name /*, opt_args... */ ){
        X_Node_updateTimerID && X_Node_startUpdate();
        
        raw  = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );
+       
        if( !raw ) return;
        
        if( name === 'scrollTo' ){
-               raw.scrollLeft = arguments[ 1 ] || 0;
-               raw.scrollTop  = arguments[ 2 ] || 0;
+               raw.scrollLeft = args[ 1 ] || 0;
+               raw.scrollTop  = args[ 2 ] || 0;
                return;
        };
        
+       if( name === 'inView' ){
+               body   = document.body;
+               child  = raw;
+               visibleX = visibleY = visibleW = visibleH = 0;
+               while( child !== body ){
+                       parent   = child.parentNode || child.parentElement;
+                       parentH  = parent.clientHeight;
+                       parentW  = parent.clientWidth;
+                       parentSW = parent.scrollHeight;
+                       parentSH = parent.scrollWidth;
+                       // 親がスクロール領域を持つ
+                       if( parentH < parentSH || parentW < parentSW ){
+                               childX   = child.offsetLeft + visibleX;
+                               childY   = child.offsetTop  + visibleY;
+                               childW   = visibleW || child.offsetWidth;
+                               childH   = visibleH || child.offsetHeight;
+                               parentSX = parent.scrollLeft;
+                               parentSY = parent.scrollTop;
+                               // 子が表示領域内
+                               if( parentSY < childY   + childH &&
+                           childY   < parentSY + parentH &&
+                           parentSX < childX   + childW  &&
+                           childX   < parentSX + parentW ){
+                               
+                           // right:子の左側が見えている left:子の左側が見えている both:完全に見えている
+                                       visiblePartX =
+                                               childX < parentSX ? 'right' :
+                                               ( parentSX + parentW ) < ( childX + childW ) ? 'left' : 'both';
+                                       visiblePartY = 
+                                               childY < parentSY ? 'bottom' :
+                                               ( parentSY + parentH ) < ( childY + childH ) ? 'top' : 'both';
+
+                                       // 子が見える領域
+                                       visibleX = visiblePartX === 'right'  ? 0 : childX - parentSX;
+                                       visibleY = visiblePartX === 'bottom' ? 0 : childY - parentSY;
+                                       visibleW =
+                                               visiblePartX === 'both'   ? childW :
+                                               visiblePartX === 'right'  ? ( parentSX + parentW - childX ) : ( childX + childW - parentSX );
+                                       visibleH =
+                                               visiblePartY === 'both'   ? childH :
+                                               visiblePartY === 'bottom' ? ( parentSY + parentH - childY ) : ( childY + childH - parentSY );           
+                   } else {
+                       return { 'isInView' : false };
+                   };
+                       };
+                       child = parent;         
+               };
+               return { 'isInView' : true };
+       };
+       
        func = raw[ name ];
        if( X_Type_isFunction( func ) ){
                if( l ){
-                       args = X_Object_cloneArray( arguments );
+                       args = X_Array_copy( args );
                        args.shift();
                        return func.apply( raw, args );
                };
                return raw[ name ]();           
        } else
-       if( X_Type_isUnknown( func ) ){
+       if( X_UA[ 'IE' ] < 9 && ( X_Type_isUnknown( func ) || X_Type_isObject( func ) ) ){
                // typeof func === unknown に対策
                // http://la.ma.la/blog/diary_200509031529.htm          
                if( l ){
-                       args = X_Object_cloneArray( arguments );
+                       args = X_Array_copy( args );
                        args.shift();
                        
                params = [];
@@ -1207,7 +1309,7 @@ function X_Node_call( name /*, opt_args... */ ){
 function X_Node_each( func /*, opt_args */ ){
        var args;
        if( 1 < arguments.length ){
-               args = X_Object_cloneArray( arguments );
+               args = X_Array_copy( arguments );
                args[ 0 ] = 0;          
                func.apply( this, args );
        } else {
@@ -1230,7 +1332,7 @@ function X_Node_reserveUpdate(){
 var X_Node_updateReservedByReleaseGPU = false;
 
 function X_Node_startUpdate( time ){
-       var removal, i, xnode;
+       var removal, i, xnodeOrElm;
        
        if( !X_Node_updateTimerID || X_ViewPort_readyState < X_EVENT_INIT ){
                return;
@@ -1248,10 +1350,23 @@ function X_Node_startUpdate( time ){
 
        if( i = removal.length ){
                for( ; i; ){
-                       xnode = removal[ --i ];
+                       xnodeOrElm = removal[ --i ];
                        // TODO GPU レイヤーの子の場合、remove をスキップする。 非GPU レイヤーへ apppend される場合、clone する?
-                       X_Node__actualRemove( xnode );
-                       ( xnode[ '_flags' ] & X_NodeFlags_EXIST ) === 0 && xnode[ 'kill' ]();
+                       if( !xnodeOrElm[ 'instanceOf' ] ){
+                               if( X_UA_DOM.IE4 ){
+                                       xnodeOrElm.removeAttribute( 'id' ); // ?
+                                       xnodeOrElm.outerHTML = ''; // xnodeOrElm.remove() ?
+                               } else {
+                                       if( !X_UA[ 'MacIE' ] ){
+                                               // elm.parentNode.tagName for ie7
+                                               xnodeOrElm.parentNode && xnodeOrElm.parentNode.tagName && xnodeOrElm.parentNode.removeChild( xnodeOrElm );
+                                       } else {
+                                               xnodeOrElm.parentNode && xnodeOrElm.parentNode.tagName && X_TEMP._fixed_remove( xnodeOrElm, that );
+                                       };
+                               };
+                       } else {
+                               X_Node__actualRemove( xnodeOrElm );
+                       };
                };
                removal.length = 0;
        };
@@ -1364,7 +1479,11 @@ var X_Node__commitUpdate =
                                                                that[ '_cssText' ] ? ' style="' + that[ '_cssText' ] + '"' : '',
                                                        '>' ].join( '' ) );
                                } else {
-                                       that[ '_rawObject' ] = elm = document.createElement( that[ '_tag' ] );
+                                       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' ] );
+                                       };
                                };
                                
                                // IE には要素追加のタイミングで起こるメモリリークがありここで追加
@@ -1378,10 +1497,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;
@@ -1568,11 +1687,21 @@ var X_Node__updateRawNode =
                        };
                        // id
                        if( that[ '_flags' ] & X_NodeFlags_DIRTY_ID ){
-                               that[ '_id' ] ? ( elm.id = that[ '_id' ] ) : ( elm.id && elm.removeAttribute( 'id' ) );         
+                               that[ '_id' ] ?
+                                       ( ( that[ '_flags' ] & X_NodeFlags_IS_SVG ) ?
+                                               elm.setAttribute( 'id', that[ '_id' ] ) :
+                                               ( elm.id = that[ '_id' ] )
+                                       ) :
+                                       ( elm.id && elm.removeAttribute( 'id' ) );              
                        };
                        // className
                        if( that[ '_flags' ] & X_NodeFlags_DIRTY_CLASSNAME ){
-                               that[ '_className' ] ? ( elm.className = that[ '_className' ] ) : ( elm.className && elm.removeAttribute( X_UA[ 'IE' ] < 8 ? 'className' : 'class' ) ); // className は ie7-                   
+                               that[ '_className' ] ?
+                                       ( ( that[ '_flags' ] & X_NodeFlags_IS_SVG ) ?
+                                               elm.setAttribute( 'class', that[ '_className' ] ) :
+                                               ( elm.className = that[ '_className' ] )
+                                       ) :
+                                       ( elm.className && elm.removeAttribute( X_UA[ 'IE' ] < 8 ? 'className' : 'class' ) ); // className は ie7-                     
                        };
                        
                        // attr
@@ -1585,7 +1714,8 @@ var X_Node__updateRawNode =
                                        switch( that[ '_tag' ] + k ){
                                                case 'TEXTAREAvalue' :
                                                        // IETester 5.5 ではエラーが出なかった.MultipulIE5.5 ではエラーが出たので
-                                                       if( !X_UA[ 'MacIE' ] && X_UA[ 'IE5x' ] ){
+                                                       // MultipleIE6 でもここを通す。X_UA[ 'ieExeComError' ] の場合 MultipleIE6
+                                                       if( ( !X_UA[ 'MacIE' ] && X_UA[ 'IE5x' ] ) || ( X_UA[ 'ieExeComError' ] && X_UA[ 'IE6' ] ) ){
                                                                elm.firstChild ?
                                                                        ( elm.firstChild.data = v || '' ) :
                                                                        elm.appendChild( document.createTextNode( v || '' ) );
@@ -1613,7 +1743,10 @@ var X_Node__updateRawNode =
                                        // TODO IE では input, なぜか button, object も type, name の変更が出来ない、同値で置き換えようとしても不可
                                        v === undefined ?
                                                elm.removeAttribute( rename[ k ] || k ) :
-                                               ( elm[ rename[ k ] || k ] = X_Node_Attr_noValue[ k ] ? k : v );
+                                       ( ( that[ '_flags' ] & X_NodeFlags_IS_SVG ) ?
+                                               elm.setAttribute( k, v ) :
+                                               ( elm[ rename[ k ] || k ] = X_Node_Attr_noValue[ k ] ? k : v )
+                                       );
                                };
                                delete that[ '_newAttrs' ];
                        };
@@ -1884,7 +2017,7 @@ var X_Node__actualRemove =
 
                        elm.removeAttribute( 'id' ); // ?
                        //document.all[ that[ '_id' ] || ( 'ie4uid' + that[ '_uid' ] ) ] = null; // MacIE5 でエラー
-                       if( !isChild ) elm.outerHTML = '';
+                       if( !isChild ) elm.outerHTML = ''; // elm.remove() ?
                        delete that[ '_rawObject' ];
                }) :
                (function(){});