X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F02_dom%2F20_XNode.js;h=b0c37239c6a58a10a46fba0d4930f2e42729299e;hb=a720658bd6302a1bd5efae47333b6df793370f3d;hp=7fb2e40b58a61f24d262781330399a801a353218;hpb=1ed2190f012cf923f7e48d3c0d122aa56c56c5f3;p=pettanr%2FclientJs.git diff --git a/0.6.x/js/02_dom/20_XNode.js b/0.6.x/js/02_dom/20_XNode.js index 7fb2e40..b0c3723 100644 --- a/0.6.x/js/02_dom/20_XNode.js +++ b/0.6.x/js/02_dom/20_XNode.js @@ -8,8 +8,7 @@ */ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ]( 'X.Node', - X_Class.POOL_OBJECT, - + X_Class.NONE, { /** * 要素に振られるユニーク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' ] ] ); }; @@ -446,6 +445,7 @@ function X_Node_toggleInGPUFlag( gpuRoot, xnodes, flag ){ */ function X_Node_create( tag, opt_attrs, opt_css ){ var xnode; + if( !this[ '_tag' ] ) return; this[ 'append' ]( xnode = X_Doc_create( tag, opt_attrs, opt_css ) ); return xnode; @@ -562,7 +562,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 +638,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 +768,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 +792,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 +822,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 +839,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 +1100,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 +1215,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 +1233,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 +1382,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 +1418,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 +1433,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 +1461,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 +1470,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 +1478,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 +1487,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 ? @@ -1533,15 +1545,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 +1575,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 +1690,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 +1765,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 +1801,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 +1984,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 +2004,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 +2047,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; };