OSDN Git Service

Version 0.6.131, cleanup X.EventDispatcher.
[pettanr/clientJs.git] / 0.6.x / js / 02_dom / 02_XNode.js
index 26060f5..cbfcdf6 100644 (file)
@@ -9,7 +9,7 @@ var
                STYLE_IS_INVISIBLE     : 2 <<  2, // visibility : hidden or opacity : 0\r
                STYLE_IS_POS_ABSOLUTE  : 2 <<  3, // position   : absolute\r
                STYLE_IS_NO_OVERFLOW   : 2 <<  4, // overflow   : hidden\r
-               STYLE_IS_WIDTH_LENGTH  : 2 <<  5, // width  : width() のための commitUpdate が不要\r
+               STYLE_IS_WIDTH_LENGTH  : 2 <<  5, // width  : overflow:hidden,要素無し、または要素が非表示なら、 width() のための commitUpdate が不要\r
                STYLE_IS_WIDTH_PCT     : 2 <<  6, // width  : width() のための commitUpdate が不要かもしれない。(親で LENGTH が指定されているなら)\r
                STYLE_IS_HEIGHT_LENGTH : 2 <<  7, // height :\r
                STYLE_IS_HEIGHT_PCT    : 2 <<  8, // height :\r
@@ -18,34 +18,33 @@ var
 \r
                DIRTY_POSITION         : 2 << 11, // 要素位置の変更が起こった。\r
                DIRTY_CONTENT          : 2 << 12, // width, height, x, y textNode の内容 TODO html と排他なので ID と共通でいい\r
-               DIRTY_ID               : 2 << 13, // width, height, x, y\r
-               DIRTY_CLASSNAME        : 2 << 14, // X_Node_CSS_getCharSize, width, height, x, y\r
-               DIRTY_ATTR             : 2 << 15, // X_Node_CSS_getCharSize, width, height, x, y\r
-               DIRTY_CSS              : 2 << 16, // X_Node_CSS_getCharSize, width, height, x, y\r
-               DIRTY_IE_FILTER        : X_UA.IE < 10 && X_UA.ActiveX ? 2 << 17 : 0, // \r
+               DIRTY_ID               : 2 << 12, // width, height, x, y\r
+               DIRTY_CLASSNAME        : 2 << 13, // X_Node_CSS_getCharSize, width, height, x, y\r
+               DIRTY_ATTR             : 2 << 14, // X_Node_CSS_getCharSize, width, height, x, y\r
+               DIRTY_CSS              : 2 << 15, // X_Node_CSS_getCharSize, width, height, x, y\r
+               DIRTY_IE_FILTER        : X_UA.IE < 10 && X_UA.ActiveX ? 2 << 16 : 0, // \r
 \r
-               \r
-               ELM_NEED_INIT          : 2 << 18,\r
-               OLD_ATTRTEXT           : 2 << 19,\r
-               OLD_CSSTEXT            : 2 << 20,\r
+               ACTUAL_LISTENING       : 2 << 17,\r
+               OLD_ATTRTEXT           : 2 << 18,\r
+               OLD_CSSTEXT            : 2 << 19,\r
 \r
                // filter 要素が親子になると不具合が出るのを検出\r
-               IE_FILTER_NOW          : 2 << 21,\r
+               IE_FILTER_NOW          : 2 << 20,\r
 \r
                //GPU_WAITING            : 2 << 20, // 1:子のGPU解除待\r
-               GPU_RESERVED           : 2 << 22, // 2:GPU予約\r
-               GPU_NOW                : 2 << 23, // 3:GPU now!\r
-               GPU_RELEASE_RESERVED   : 2 << 24, // 4:GPU解除予約\r
+               GPU_RESERVED           : 2 << 21, // 2:GPU予約\r
+               GPU_NOW                : 2 << 22, // 3:GPU now!\r
+               GPU_RELEASE_RESERVED   : 2 << 23, // 4:GPU解除予約\r
                \r
-               IE4_HAS_TEXTNODE       : X_UA.IE4 ? 2 << 22 : 0,\r
-               IE4_HAS_ELEMENT        : X_UA.IE4 ? 2 << 23 : 0,\r
-               IE4_DIRTY_CHILDREN     : X_UA.IE4 ? 2 << 24 : 0,\r
-               IE4_FIXED              : X_UA.IE4 ? 2 << 25 : 0,\r
+               IE4_HAS_TEXTNODE       : X_UA.IE4 ? 2 << 21 : 0,\r
+               IE4_HAS_ELEMENT        : X_UA.IE4 ? 2 << 22 : 0,\r
+               IE4_DIRTY_CHILDREN     : X_UA.IE4 ? 2 << 23 : 0,\r
+               IE4_FIXED              : X_UA.IE4 ? 2 << 24 : 0,\r
                \r
-               IE5_DISPLAY_NONE_FIX   : X_UA.IE5 && X_UA.ActiveX ? 2 << 25 : 0\r
+               IE5_DISPLAY_NONE_FIX   : X_UA.IE5 && X_UA.ActiveX ? 2 << 24 : 0\r
        },\r
 \r
-       X_Node_BITMASK_RESET_STYLE = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ (\r
+       X_Node_BITMASK_RESET_STYLE  = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ (\r
                X_Node_State.STYLE_IS_DISPLAY_NONE |\r
                X_Node_State.STYLE_IS_INVISIBLE |\r
                X_Node_State.STYLE_IS_POS_ABSOLUTE |\r
@@ -57,15 +56,15 @@ var
                X_Node_State.STYLE_IS_FONT_LENGTH |\r
                X_Node_State.STYLE_IS_FONT_PCT ),\r
 \r
-       X_Node_BitMask_IS_DIRTY = X_Node_State.DIRTY_POSITION | \r
+       X_Node_BitMask_IS_DIRTY     = X_Node_State.DIRTY_POSITION | \r
                X_Node_State.DIRTY_CONTENT | X_Node_State.DIRTY_ID | X_Node_State.DIRTY_CLASSNAME |\r
                X_Node_State.DIRTY_ATTR | X_Node_State.DIRTY_CSS | X_Node_State.DIRTY_IE_FILTER,\r
 \r
-       X_Node_BitMask_RESET_DIRTY = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ X_Node_BitMask_IS_DIRTY,\r
+       X_Node_BitMask_RESET_DIRTY  = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ X_Node_BitMask_IS_DIRTY,\r
        \r
-       X_Node_BitMask_RESET_GPU = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ ( X_Node_State.GPU_RESERVED | X_Node_State.GPU_NOW | X_Node_State.GPU_RELEASE_RESERVED ),\r
+       X_Node_BitMask_RESET_GPU    = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ ( X_Node_State.GPU_RESERVED | X_Node_State.GPU_NOW | X_Node_State.GPU_RELEASE_RESERVED ),\r
        \r
-       X_Node_BitMask_IE4_IS_MIX = X_Node_State.IE4_HAS_TEXTNODE | X_Node_State.IE4_HAS_ELEMENT,\r
+       X_Node_BitMask_IE4_IS_MIX   = X_Node_State.IE4_HAS_TEXTNODE | X_Node_State.IE4_HAS_ELEMENT,\r
        \r
        X_Node_TYPE = {\r
                XNODE       : 1,\r
@@ -106,7 +105,7 @@ var
                _uid       : 0,\r
                _flags     : X_Node_State.DESTROYED,\r
 \r
-               _rawObject : null,\r
+               // _rawObject : null,\r
                _rect      : null, // \r
                _fontSize  : 0,\r
                \r
@@ -224,7 +223,7 @@ var
                \r
                appendTo       : X_Node_appendTo,\r
                \r
-               appendToRoot   : X_Node_appendToRoot,\r
+               appendToRoot   : X_Node_appendToRoot, // remove\r
                \r
                before         : X_Node_before, // remove\r
                \r
@@ -676,27 +675,29 @@ function X_Node_destroy( isChild ){
 };\r
 \r
 function X_Node_onBeforeKill( e ){\r
-       var xnodes = this._xnodes,\r
-               elm = this._rawObject || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this ),\r
-               i;\r
-       \r
-       if( !this._flags ) return;\r
+       var xnodes = this._xnodes, i, elm;\r
        \r
-       delete X_Node_CHASHE[ this._uid ];\r
+       if( !this._flags ) return X.Callback.NONE;\r
        \r
+       elm = this._rawObject || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );\r
+       elm && this._listeners && this.unlisten(); // イベントの退避\r
+\r
        if( xnodes && ( i = xnodes.length ) ){\r
                for( ; i; ){\r
                        X_Node_onBeforeKill.call( xnodes[ --i ] );\r
                };\r
        };\r
 \r
-       e && this.remove();\r
-       elm && this._listeners && this.unlisten(); // イベントの退避\r
-       \r
-       if( e && elm && elm.parentNode && elm.parentNode.tagName ){\r
-               delete this._flags;\r
-               return X.Callback.PREVENT_DEFAULT;\r
+       delete X_Node_CHASHE[ this._uid ];\r
+\r
+       if( e ){\r
+               this.remove();\r
+               if( X_Node_reserveRemoval[ X_Node_reserveRemoval.length - 1 ] === this ){\r
+                       delete this._flags;\r
+                       return X.Callback.PREVENT_DEFAULT;              \r
+               };              \r
        };\r
+       return X.Callback.NONE;\r
 };\r
 \r
 \r
@@ -1039,6 +1040,7 @@ function X_Node_startUpdate( time ){
        if( i = removal.length ){\r
                for( ; i; ){\r
                        xnode = removal[ --i ];\r
+                       // TODO GPU レイヤーの子の場合、remove をスキップする。 非GPU レイヤーへ apppend される場合、clone する?\r
                        X_Node__actualRemove( xnode );\r
                        !xnode._flags && xnode.kill();\r
                };\r
@@ -1066,8 +1068,8 @@ function X_Node_startUpdate( time ){
 };\r
 \r
 /*\r
- * 1. GPU_NOW の場合、これ以下の一切の更新を行わない\r
- * 2. GPU解放予約 の場合、この要素のみ変更を行う。rAF 後にさらに更新するためフラグを立てる。\r
+ * 1. GPU_NOW の場合、子の変更は行わない\r
+ * 2. GPU解放予約 の場合//、この要素のみ変更を行う。rAF 後にさらに更新するためフラグを立てる。\r
  * 3. GPU予約 -> GPU\r
  * 4. style="display:none" の場合、これ以下の変更を行わない。\r
  * 5. ie5 非表示フラグが立っていて、親と自身の class・id によって非表示になっていて、親と自身に変更がない。accumulatedFlags を使用。\r
@@ -1118,7 +1120,7 @@ var X_Node__commitUpdate =
                                        return nextElement;\r
                                };\r
                                elm && ( elm.style.display = 'none' );\r
-                               return elm.nextSibling === nextElement ? elm : nextElement;\r
+                               return ( elm && elm.nextSibling === nextElement ) ? elm : nextElement;\r
                        };\r
                        \r
                        // 5. ie5 非表示fixフラグ\r
@@ -1140,7 +1142,7 @@ var X_Node__commitUpdate =
                                        };\r
                                } else\r
                                if( X_Node_strictElmCreation ){\r
-                                       that._flags & X_Node_State.DIRTY_CSS && X_Node_CSS_objToCssText( that, true );\r
+                                       that._flags & X_Node_State.OLD_CSSTEXT && X_Node_CSS_objToCssText( that, true ); // OLD_CSSTEXT ??\r
                \r
                                        that._rawObject = elm =\r
                                                document.createElement( [\r
@@ -1148,9 +1150,9 @@ var X_Node__commitUpdate =
                                                                ' UID="', that._uid, '"',\r
                                                                that._id ? ' id="' + that._id + '"' : '',\r
                                                                that._className ? ' class="' + that._className + '"' : '',\r
-                                                               that._flags & X_Node_State.OLD_ATTRTEXT ? X_Node_Attr_objToAttrText( that ) : that._attrText,\r
+                                                               X_Node_Attr_objToAttrText( that, true ),\r
                                                                that._cssText ? ' style="' + that._cssText + '"' : '',\r
-                                                       '>' ].join( '' ) );             \r
+                                                       '>' ].join( '' ) );\r
                                } else {\r
                                        that._rawObject = elm = document.createElement( that._tag );\r
                                };\r
@@ -1163,18 +1165,17 @@ var X_Node__commitUpdate =
                                };\r
 \r
                                if( that._tag ){\r
-                                       // src の onload があるので先ではないか?\r
-                                       // TODO ie の str から要素を作る場合、srcだけ イベント設定後ではないか?\r
                                        X_EventDispatcher_toggleAllEvents( that, true );// イベントの復帰                                \r
+                                       that._flags |= X_Node_State.ACTUAL_LISTENING;\r
                                        \r
                                        if( X_Node_documentFragment ){\r
                                                //( frg = X_Node_documentFragment ).appendChild( elm );\r
                                        };\r
 \r
                                        if( X_Node_strictElmCreation ){\r
-                                               // TODO src 等の設定\r
-                                               delete that._newAttrs;\r
                                                that._flags &= X_Node_BitMask_RESET_DIRTY;\r
+                                               // ie の string から要素を作る場合、ネットワーク系属性は onload イベントなどを拾うために、要素生成->イベント復帰後に適用する\r
+                                               that._newAttrs && ( that._flags |= X_Node_State.DIRTY_ATTR ); // Network 系の属性は遅らせて設定\r
                                                that._flags |= X_Node_State.DIRTY_IE_FILTER;// doc 追加後に filter を指定しないと有効にならない。\r
                                        } else {\r
                                                elm.UID = that._uid;\r
@@ -1185,7 +1186,7 @@ var X_Node__commitUpdate =
                                                // http://outcloud.blogspot.jp/2010/09/iframe.html\r
                                                // この問題は firefox3.6 で確認\r
                                                if( X_UA.Gecko ){\r
-                                                       if( that._tag === 'IFRAME' && !that._attrs[ 'src' ] ){\r
+                                                       if( that._tag === 'IFRAME' && ( !that._attrs || !that._attrs[ 'src' ] ) ){\r
                                                                //elm.contentWindow.location.replace = elm.src = 'about:blank';\r
                                                                that.attr( 'src', 'about:blank' );\r
                                                        };\r
@@ -1200,19 +1201,19 @@ var X_Node__commitUpdate =
                                nextElement ?\r
                                        parentElement.insertBefore( elm, nextElement ) :\r
                                        parentElement.appendChild( elm );\r
-\r
-                               if( X_Node_displayNoneFixForIE5 ) that._flags |= X_Node_State.DIRTY_POSITION;\r
                        };\r
                        \r
-                       that._flags & X_Node_State.DIRTY_POSITION && X_EventDispatcher_toggleAllEvents( that, true );// イベントの復帰\r
-                       that._flags &= ~X_Node_State.DIRTY_POSITION;\r
+                       if( that._listeners && ( that._flags & X_Node_State.ACTUAL_LISTENING ) === 0 ){\r
+                               X_EventDispatcher_toggleAllEvents( that, true );// イベントの退避\r
+                               that._flags |= X_Node_State.ACTUAL_LISTENING;\r
+                       };\r
                        \r
                        // 8. 更新の適用\r
-                       if( accumulatedFlags & X_Node_BitMask_IS_DIRTY ) delete that._fontSize;\r
-                       \r
-                       that._flags & X_Node_BitMask_IS_DIRTY && X_Node__updateRawNode( that, elm );\r
-                               \r
-                       \r
+                       if( accumulatedFlags & X_Node_BitMask_IS_DIRTY ){\r
+                               delete that._fontSize;\r
+                               X_Node__updateRawNode( that, elm );\r
+                       };\r
+\r
                        // 9. ie5 only\r
                        // 親及び自身へのクラス・id指定で display : none になるケースがありそれを検出\r
                        // 生成と破棄が繰り返されてしまう、親と自身の id, class が変わった場合だけ再生成。 accumulatedFlags & ( ID | CLASSNAME )\r
@@ -1266,7 +1267,7 @@ var X_Node__commitUpdate =
                                                return prevElement;\r
                                        };\r
                                };\r
-                               return elm || nextElement;\r
+                               return elm || prevElement;\r
                        };\r
                        \r
                        if( !elm ){\r
@@ -1341,7 +1342,6 @@ var X_Node__commitUpdate =
                (function(){});\r
 \r
 /*\r
- * TODO IE5 は filter-fix があるため、親から変更を適用し、自信の display:none を調べる\r
  * GPU レイヤーするブラウザは、子要素から変更を当てていく? <- とりあえず、親要素から。\r
  */\r
 var X_Node__updateRawNode =\r
@@ -1416,7 +1416,6 @@ var X_Node__updateRawNode =
                                } else {\r
                                        elm.style.cssText = ''; // IE5.5以下 Safari3.2 で必要\r
                                        elm.removeAttribute( 'style' );\r
-                                       delete that._cssText;\r
                                };\r
                        } else\r
                        if( that._flags & X_Node_State.DIRTY_IE_FILTER ){\r
@@ -1461,7 +1460,6 @@ var X_Node__updateRawNode =
                                } else {\r
                                        elm.style.cssText = '';\r
                                        elm.removeAttribute( 'style' );\r
-                                       delete that._cssText;\r
                                };\r
                        } else\r
                        if( that._flags & X_Node_State.DIRTY_IE_FILTER ){\r
@@ -1519,12 +1517,12 @@ var X_Node__actualCreate =
                } else {\r
                        if( !isChild ) X_Node__actualRemove( that, /* true */ false );\r
                        \r
-                       that._flags & X_Node_State.DIRTY_CSS && X_Node_CSS_objToCssText( that, true );\r
+                       that._flags & X_Node_State.OLD_CSSTEXT && X_Node_CSS_objToCssText( that, true );\r
                        \r
                        html = [\r
                                '<', that._tag, ' id=', ( that._id || ( 'ie4uid' + uid ) ), ' UID="', uid, '"',\r
                                that._className ? ' class="' + that._className + '"' : '',\r
-                               that._flags & X_Node_State.OLD_ATTRTEXT ? X_Node_Attr_objToAttrText( that ) : that._attrText,\r
+                               X_Node_Attr_objToAttrText( that, true ),\r
                                that._cssText ? ' style="' + that._cssText + '"' : '',\r
                        '>' ];\r
                        \r
@@ -1557,7 +1555,7 @@ var X_Node__actualCreate =
                        };\r
                        X_Dom_DTD_EMPTY[ that._tag ] || ( html[ n ] = '<\/' + that._tag + '>' );\r
                        \r
-                       delete that._newAttrs;\r
+                       that._newAttrs && ( that._flags |= X_Node_State.DIRTY_ATTR );\r
                };\r
                \r
                return html.join( '' );\r
@@ -1574,8 +1572,12 @@ var X_Node__afterActualCreate =
                                X_Node__afterActualCreate( xnodes[ --i ] );\r
                        };\r
                };\r
-               that._flags & X_Node_State.DIRTY_IE_FILTER && X_Node__updateRawNode( that, that._rawObject || X_Node__ie4getRawNode( that ) );\r
-               that._flags &= X_Node_BitMask_RESET_DIRTY;\r
+               // ネットわーう系属性と filter は要素生成後に適用\r
+               if( that._flags & ( X_Node_State.DIRTY_ATTR | X_Node_State.DIRTY_IE_FILTER ) ){\r
+                       X_Node__updateRawNode( that, that._rawObject || X_Node__ie4getRawNode( that ) );\r
+               } else {\r
+                       that._flags &= X_Node_BitMask_RESET_DIRTY;\r
+               };\r
                X_EventDispatcher_toggleAllEvents( that, true );// イベントの復帰\r
        });\r
 \r
@@ -1597,7 +1599,10 @@ var X_Node__actualRemove =
 \r
                        if( !elm ) return;\r
                        \r
-                       that._listeners && X_EventDispatcher_toggleAllEvents( that, false );// イベントの退避\r
+                       if( that._flags & X_Node_State.ACTUAL_LISTENING ){\r
+                               that._listeners && X_EventDispatcher_toggleAllEvents( that, false );// イベントの退避\r
+                               that._flags &= ~X_Node_State.ACTUAL_LISTENING;\r
+                       };\r
                        \r
                        // ie5では filter の効いている要素をremove時に破棄して、再度append 時に新規生成する\r
                        // ちなみに elm.filters に触ると ie8 でなぜかカラム落ちが発生、、、\r
@@ -1606,10 +1611,23 @@ var X_Node__actualRemove =
                                        //elm.style.removeAttribute( 'filter' );\r
                                        isChild = false;\r
                                        delete that._rawObject;\r
-                                       // 破棄前に value を控える TODO checked, selected も!\r
+                                       // 破棄前にインタラクティブな属性値を控える\r
                                        if( X_Node_Attr_HAS_VALUE[ that._tag ] && ( !that._newAttrs || !X_Object_inObject( 'value', that._newAttrs ) ) ){\r
+                                               if( !that._attrs ) that._attrs = {};\r
                                                that._attrs.value = elm.value;\r
                                        };\r
+                                       if( that._tag === 'OPTION' && ( !that._newAttrs || !X_Object_inObject( 'selected', that._newAttrs ) ) ){\r
+                                               if( !that._attrs ) that._attrs = {};\r
+                                               that._attrs.selected = elm.selected;\r
+                                       };\r
+                                       if( that._tag === 'SELECT' && ( !that._newAttrs || !X_Object_inObject( 'selectedIndex', that._newAttrs ) ) ){\r
+                                               if( !that._attrs ) that._attrs = {};\r
+                                               that._attrs.selectedIndex = elm.selectedIndex;\r
+                                       };\r
+                                       if( that._tag === 'INPUT' && that._attr && ( that._attr.type === 'checkbox' || that._attr.type === 'radio' ) && ( !that._newAttrs || !X_Object_inObject( 'checked', that._newAttrs ) ) ){\r
+                                               that._attrs.checked = elm.checked;\r
+                                       };\r
+                                       // 子要素への参照を外す\r
                                        elm.innerHTML = '';\r
                                };\r
                        };\r
@@ -1635,10 +1653,24 @@ var X_Node__actualRemove =
                        if( !elm ) return;\r
                        that._listeners && X_EventDispatcher_toggleAllEvents( that, false );// イベントの退避\r
                        \r
-                       // 破棄前に value を控える TODO checked, selected も!\r
+                       // 破棄前にインタラクティブな属性値を控える\r
                        if( X_Node_Attr_HAS_VALUE[ that._tag ] && ( !that._newAttrs || !X_Object_inObject( 'value', that._newAttrs ) ) ){\r
+                               if( !that._attrs ) that._attrs = {};\r
                                that._attrs.value = elm.value;\r
                        };\r
+                       if( that._tag === 'OPTION' && ( !that._newAttrs || !X_Object_inObject( 'selected', that._newAttrs ) ) ){\r
+                               if( !that._attrs ) that._attrs = {};\r
+                               that._attrs.selected = elm.selected;\r
+                       };\r
+                       if( that._tag === 'SELECT' && ( !that._newAttrs || !X_Object_inObject( 'selectedIndex', that._newAttrs ) ) ){\r
+                               if( !that._attrs ) that._attrs = {};\r
+                               that._attrs.selectedIndex = elm.selectedIndex;\r
+                       };\r
+                       if( that._tag === 'INPUT' && that._attr && ( that._attr.type === 'checkbox' || that._attr.type === 'radio' ) && ( !that._newAttrs || !X_Object_inObject( 'checked', that._newAttrs ) ) ){\r
+                               if( !that._attrs ) that._attrs = {};\r
+                               that._attrs.checked = elm.checked;\r
+                       };\r
+\r
                        elm.removeAttribute( 'id' ); // ?\r
                        //document.all[ that._id || ( 'ie4uid' + that._uid ) ] = null; // MacIE5 でエラー\r
                        if( !isChild ) elm.outerHTML = '';\r