OSDN Git Service

Version 0.6.145, fix X.Audio, fix VIEW_ACTIVATE Event @X.ViewPort.
[pettanr/clientJs.git] / 0.6.x / js / 02_dom / 02_XNode.js
index b3e6576..d71a866 100644 (file)
@@ -68,7 +68,7 @@ var   X_Node_BITMASK_RESET_STYLE  = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ (
        \r
        X_Node_BitMask_IE4_IS_MIX   = X_Node_State.IE4_HAS_TEXTNODE | X_Node_State.IE4_HAS_ELEMENT,\r
        \r
-       /** @enum {number} */\r
+       /* @enum {number} */\r
        X_Node_TYPE = {\r
                XNODE       : 1,\r
                RAW_HTML    : 2,\r
@@ -109,7 +109,7 @@ var X_Node_BITMASK_RESET_STYLE  = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ (
  */\r
 var    Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](\r
        'X.Node',\r
-       X_Class.POOL_OBJECT, // X_Class.FINAL\r
+       X_Class.POOL_OBJECT,\r
        \r
        {\r
                /**\r
@@ -142,7 +142,6 @@ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](
                /**\r
                 * NodeList と動作を一致させるためのプロパティ。常に 1。\r
                 * @type {number}\r
-                * @private\r
                 * @alias Node.prototype.length\r
                 */\r
                length       : 1,\r
@@ -150,7 +149,6 @@ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](
                /**\r
                 * 親 Node。\r
                 * @type {Node}\r
-                * @private\r
                 * @alias Node.prototype.parent\r
                 */\r
                parent       : null, // remove された枝も親子構造は維持している。\r
@@ -313,8 +311,8 @@ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](
                                                return X_Node_none;\r
 \r
                                        default :\r
-                                               this.length = 0;\r
                                                if( X_Node_none ) return X_Node_none;\r
+                                               this.length = 0;\r
                                                return;\r
                                };\r
                        };\r
@@ -324,6 +322,8 @@ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](
                        };\r
                        this[ '_flags' ] |= X_Node_State.EXIST;\r
                        X_Node_CHASHE[ this[ '_uid' ] = uid ] = this;\r
+                       \r
+                       X_EventDispatcher_systemListen( this, X_EVENT_BEFORE_KILL_INSTANCE, X_Node_onBeforeKill );\r
                },\r
                \r
                // attr\r
@@ -347,9 +347,9 @@ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](
                \r
                'appendTo'       : X_Node_appendTo,\r
                \r
-               'prev'           : X_Node_before,\r
+               'prev'           : X_Node_prev,\r
                \r
-               'next'           : X_Node_after,\r
+               'next'           : X_Node_next,\r
                \r
                'swap'           : X_Node_swap,\r
                \r
@@ -357,13 +357,11 @@ var       Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](
                \r
                'empty'          : X_Node_empty,\r
                \r
-               destroy          : X_Node_destroy, // -> kill && kill event\r
-               \r
                'contains'       : X_Node_contains,\r
                \r
                'getChildAt'     : X_Node_getChildAt,\r
                \r
-               'numChildren'    : X_Node_length,\r
+               'numChildren'    : X_Node_numChildren,\r
                \r
                'firstChild'     : X_Node_firstChild,\r
                \r
@@ -397,6 +395,7 @@ function X_Node_getType( v ){
        if( X_Type_isString( v ) ){\r
                return '<' === v.charAt( 0 ) && v.charAt( v.length - 1 ) === '>' ? X_Node_TYPE.HTML_STRING : X_Node_TYPE.STRING;\r
        };\r
+       if( v[ 'instanceOf' ] && v[ 'instanceOf' ]( Node ) ) return X_Node_TYPE.XNODE;\r
        return 0;\r
 };\r
 function X_Node_getXNode( v ){\r
@@ -437,7 +436,7 @@ var X_Node_isXmlDocument =
                                return root.isXML = root[ '_rawObject' ].createElement( 'p' ).tagName !== root[ '_rawObject' ].createElement( 'P' ).tagName;\r
                        }),\r
        X_Node_CHASHE     = [],\r
-       X_Node_none  = X_Node_CHASHE[ 0 ] = new Node(),\r
+       X_Node_none  = X_Node_CHASHE[ 0 ] = Node(),\r
        X_Node_html, // = X_Node_CHASHE[ 1 ] <html>\r
        X_Node_head, // = X_Node_CHASHE[ 2 ] <head>\r
        X_Node_body, // = X_Node_CHASHE[ 3 ] <body>\r
@@ -562,7 +561,7 @@ function X_Node_clone( opt_clone_children ){
        var xnode, xnodes, i, l;\r
        if( this[ '_tag' ] ){\r
                X_Node_newByTag = true;\r
-               xnode = new Node( this[ '_tag' ], X_Object_clone( this[ '_attrs' ] ), X_Object_clone( this[ '_css' ] ) )\r
+               xnode = Node( this[ '_tag' ], X_Object_clone( this[ '_attrs' ] ), X_Object_clone( this[ '_css' ] ) )\r
                        [ 'attr' ]( { 'id' : this[ '_id' ] } )\r
                        [ 'className' ]( this[ '_className' ] );\r
                if( opt_clone_children && ( xnodes = this[ '_xnodes' ] ) && ( l = xnodes.length ) ){\r
@@ -573,12 +572,12 @@ function X_Node_clone( opt_clone_children ){
                return xnode;           \r
        };\r
        X_Node_newByText = true;\r
-       return new Node( this[ '_text' ] );\r
+       return Node( this[ '_text' ] );\r
 };\r
 \r
 /**\r
  * ノードを子配列の最後に追加する。文字列が渡された場合、HTMLパーサーによって Node ツリーを作成して追加する。HtmlElement, TextNode の場合は内部使用専用。\r
- * @alias Node.prototype.clone\r
+ * @alias Node.prototype.append\r
  * @param {Node|string|HTMLElement|TextNode} [v] HTMLElement と TextNode は内部のみ。\r
  * @return {Node} 自身。チェインメソッド\r
  * @example myNode.append( node );\r
@@ -600,7 +599,7 @@ function X_Node_append( v ){
        switch( X_Node_getType( v ) ){\r
                case X_Node_TYPE.RAW_HTML :\r
                case X_Node_TYPE.RAW_TEXT :\r
-                       v = new Node( v );\r
+                       v = Node( v );\r
                        break;\r
                case X_Node_TYPE.HTML_STRING :\r
                case X_Node_TYPE.STRING :\r
@@ -627,7 +626,7 @@ function X_Node_append( v ){
 \r
 /**\r
  * ノードを挿入位置に追加する。\r
- * @alias Node.prototype.clone\r
+ * @alias Node.prototype.appendAt\r
  * @param {number} index 挿入位置 0以上\r
  * @param {Node|string|HTMLElement|TextNode} [v] HTMLElement と TextNode は内部のみ。\r
  * @return {Node} 自身。チェインメソッド\r
@@ -659,7 +658,7 @@ function X_Node_appendAt( start, v ){
        switch( X_Node_getType( v ) ){\r
                case X_Node_TYPE.RAW_HTML :\r
                case X_Node_TYPE.RAW_TEXT :\r
-                       v = new Node( v );\r
+                       v = Node( v );\r
                        break;\r
                case X_Node_TYPE.HTML_STRING :\r
                case X_Node_TYPE.STRING :\r
@@ -670,7 +669,14 @@ function X_Node_appendAt( start, v ){
                        return this;\r
                case X_Node_TYPE.XNODE :\r
                        // 親の xnodes から v を消す\r
-                       v.parent && v[ 'remove' ]();\r
+                       if( v.parent ){\r
+                               if( v.parent === this ){\r
+                                       i = v[ 'getOrder' ]();\r
+                                       if( i === start ) return this;\r
+                                       if( i < start ) --start;\r
+                               };\r
+                               v[ 'remove' ]();\r
+                       };\r
                        // IE4 でテキストノードの追加、FIXED 済でない場合、親に要素の追加を通知\r
                        if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( this[ '_flags' ] & X_Node_State.IE4_FIXED ) === 0 ) this[ '_flags' ] |= X_Node_State.IE4_DIRTY_CHILDREN;\r
                        break;\r
@@ -688,10 +694,18 @@ function X_Node_appendAt( start, v ){
        return this;\r
 };\r
 \r
+/**\r
+ * ノードを親に追加する。戻り値は子ノードなので、続けて操作が出来る。\r
+ * @alias Node.prototype.appendTo\r
+ * @param {Node|string|HTMLElement} [parent] HTMLElement は内部のみ。\r
+ * @param {number} [opt_index=-1] 挿入位置。省略した場合は最後に追加する。\r
+ * @return {Node} 自身。チェインメソッド\r
+ * @example childNode.appendTo( parentNode, 1 );\r
+ */\r
 function X_Node_appendTo( parent, opt_index ){\r
        switch( X_Node_getType( parent ) ){\r
                case X_Node_TYPE.RAW_HTML :\r
-                       parent = new Node( parent );\r
+                       parent = Node( parent );\r
                        break;\r
                case X_Node_TYPE.HTML_STRING :\r
                        parent = X_HtmlParser_parse( parent, true );\r
@@ -701,15 +715,20 @@ function X_Node_appendTo( parent, opt_index ){
                default :\r
                        return this;\r
        };\r
-       opt_index === undefined ? parent[ 'append' ]( this ) : parent[ 'appendAt' ]( opt_index, this );\r
+       X_Type_isFinite( opt_index ) ? parent[ 'appendAt' ]( opt_index, this ) : parent[ 'append' ]( this );\r
        return this;\r
 };\r
 \r
-/* --------------------------------------\r
- *  Before , After, Replace\r
+\r
+/**\r
+ * ノードの直前の要素を取得。または直前に挿入。挿入する要素が先にいる兄弟でも正しく動作する。\r
+ * @alias Node.prototype.prev\r
+ * @param {Node|string|HTMLElement|TextNode} [...v] HTMLElement と TextNode は内部のみ。\r
+ * @return {Node} 自身。チェインメソッド\r
+ * @example childNode.prev( prevNode );\r
  */\r
-function X_Node_before( v ){\r
-       var parent = this.parent, xnodes, i, l, start;\r
+function X_Node_prev( v ){\r
+       var parent = this.parent, xnodes, i, l;\r
        \r
        // getter\r
        if( v === undefined ){\r
@@ -722,18 +741,24 @@ function X_Node_before( v ){
        if( !parent ) return this;\r
        \r
        l = arguments.length;\r
-       start = this[ 'getOrder' ]();\r
        if( 1 < l ){\r
-               for( ; l; ){\r
-                       parent[ 'appendAt' ]( start, arguments[ --l ] );\r
+               for( i = 0; l; ++i ){\r
+                       parent[ 'appendAt' ]( this[ 'getOrder' ]() - i, arguments[ --l ] );\r
                };\r
                return this;\r
        };\r
-       parent[ 'appendAt' ]( start, v );\r
+       parent[ 'appendAt' ]( this[ 'getOrder' ](), v );\r
        return this;\r
 };\r
 \r
-function X_Node_after( v ){\r
+/**\r
+ * ノードの直後の要素を取得。または直後に挿入。挿入する要素が先にいる兄弟でも正しく動作する。\r
+ * @alias Node.prototype.next\r
+ * @param {Node|string|HTMLElement|TextNode} [v] HTMLElement と TextNode は内部のみ。\r
+ * @return {Node} 自身。チェインメソッド\r
+ * @example childNode.next( prevNode );\r
+ */\r
+function X_Node_next( v ){\r
        var parent = this.parent, xnodes, i, l, start;\r
        \r
        // getter\r
@@ -748,33 +773,39 @@ function X_Node_after( v ){
        \r
        l = arguments.length;\r
        start = this[ 'getOrder' ]() + 1;\r
+       \r
        if( parent[ '_xnodes' ].length <= start ){\r
-               if( 1 < l ){\r
-                       for( i = 0; i < l; ++i ){\r
-                               parent[ 'append' ]( arguments[ i ] );\r
-                       };\r
-                       return this;\r
+               for( i = 0; i < l; ++i ){\r
+                       parent[ 'append' ]( arguments[ i ] );\r
                };\r
-               parent[ 'append' ]( v );\r
-               return this;\r
-       };\r
+       } else\r
        if( 1 < l ){\r
                for( ; l; ){\r
-                       parent[ 'appendAt' ]( start, arguments[ --l ] );\r
+                       parent[ 'appendAt' ]( this[ 'getOrder' ]() + 1, arguments[ --l ] );\r
                };\r
-               return this;\r
+       } else {\r
+               parent[ 'appendAt' ]( start, v );\r
        };\r
-       parent[ 'appendAt' ]( start, v );\r
        return this;\r
 };\r
 \r
+/**\r
+ * 要素の入れ替え。自身は remove() される。\r
+ * @alias Node.prototype.swap\r
+ * @param {Node|string|HTMLElement|TextNode} [v] HTMLElement と TextNode は内部のみ。\r
+ * @return {Node} 自身。チェインメソッド\r
+ * @example node.swap( newNode );\r
+ */\r
 function X_Node_swap( v ){\r
        if( !this.parent ) return this;\r
-       return arguments.length === 1 ? this[ 'prev' ]( v )[ 'remove' ]() : X_Node_before.apply( this, arguments )[ 'remove' ]();\r
+       return arguments.length === 1 ? this[ 'prev' ]( v )[ 'remove' ]() : X_Node_prev.apply( this, arguments )[ 'remove' ]();\r
 };\r
 \r
-/* --------------------------------------\r
- *  Remove\r
+/**\r
+ * 要素を抜く。\r
+ * @alias Node.prototype.remove\r
+ * @return {Node} 自身。チェインメソッド\r
+ * @example node.remove();\r
  */\r
 function X_Node_remove(){\r
        var parent = this.parent,\r
@@ -809,54 +840,30 @@ function X_Node_remove(){
        return this;\r
 };\r
 \r
+/**\r
+ * 子要素を破棄する。子要素は kill() されます。\r
+ * @alias Node.prototype.empty\r
+ * @return {Node} 自身。チェインメソッド\r
+ * @example node.empty();\r
+ */\r
 function X_Node_empty(){\r
        var xnodes = this[ '_xnodes' ], i;\r
        if( xnodes && ( i = xnodes.length ) ){\r
                for( ; i; ){\r
-                       xnodes[ --i ].destroy();\r
+                       xnodes[ --i ][ 'kill' ]();\r
                };\r
                xnodes.length = 0;\r
        };\r
        return this;\r
 };\r
 \r
-/* --------------------------------------\r
- *  TODO destory -> kill\r
- */\r
-\r
-function X_Node_destroy( isChild ){\r
-       var xnodes = this[ '_xnodes' ], i, elm;\r
-       \r
-       if( ( this[ '_flags' ] & X_Node_State.EXIST ) === 0 ) return;\r
-       \r
-       elm = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );\r
-       \r
-       if( xnodes && ( i = xnodes.length ) ){\r
-               //for( ; i; ){\r
-               //      xnodes[ --i ].destroy( true );\r
-               //};\r
-       };\r
-       elm && this[ '_listeners' ] && this[ 'unlisten' ](); // イベントの退避\r
-\r
-       if( this[ '_flags' ] & X_Node_State.IN_TREE ){\r
-               !isChild && this[ 'remove' ]();\r
-               this[ '_flags' ] &= ~X_Node_State.EXIST;\r
-       } else {\r
-               this.parent && this.parent[ '_xnodes' ].splice( this.parent[ '_xnodes' ].indexOf( this ), 1 );\r
-               elm && !isChild && X_Node__actualRemove( this );\r
-               this[ 'kill' ]();\r
-       };\r
-       \r
-       delete X_Node_CHASHE[ this[ '_uid' ] ];\r
-};\r
-\r
 function X_Node_onBeforeKill( e ){\r
        var xnodes = this[ '_xnodes' ], i, elm;\r
        \r
        if( ( this[ '_flags' ] & X_Node_State.EXIST ) === 0 ) return X_Callback_NONE;\r
        \r
        elm = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );\r
-       elm && this[ '_listeners' ] && this[ 'unlisten' ](); // イベントの退避\r
+       elm && this[ '_listeners' ] && X_EventDispatcher_unlistenAll( this ); // イベントの退避\r
 \r
        if( xnodes && ( i = xnodes.length ) ){\r
                for( ; i; ){\r
@@ -877,64 +884,100 @@ function X_Node_onBeforeKill( e ){
 };\r
 \r
 \r
-/* --------------------------------------\r
- *  contains\r
+/**\r
+ * 要素を子以下に持つか?調べる。\r
+ * @alias Node.prototype.contains\r
+ * @param {Node|string|HTMLElement|TextNode} [v] HTMLElement と TextNode は内部のみ。\r
+ * @return {boolean} \r
+ * @example node.contains( testNode );\r
  */\r
 function X_Node_contains( v ){\r
        var elm, type, xnodes, i;\r
        if( !v || !this[ '_tag' ] || this === v ) return false;\r
        // contains ie4+\r
        if( ( elm = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this ) ) && document.contains && ( type = X_Node_getType( v ) ) && ( type === X_Node_TYPE.RAW_HTML || type === X_Node_TYPE.RAW_TEXT ) ){\r
-               return elm[ 'contains' ]( v );  \r
+               return elm.contains( v );\r
        };\r
+\r
        //if( document.compareDocumentPosition ){\r
        //      \r
        //};\r
        xnodes = this[ '_xnodes' ];\r
        if( !xnodes || !xnodes.length ) return false;\r
        if( xnodes.indexOf( v ) !== -1 ) return true; // fast\r
-       if( elm === v.parentNode ) return true;\r
        for( i = xnodes.length; i; ){\r
                if( xnodes[ --i ][ 'contains' ]( v ) ) return true;\r
        };\r
        return false;\r
 };\r
 \r
-/* --------------------------------------\r
- *  getChild\r
+/**\r
+ * index の子要素を取得する。\r
+ * @alias Node.prototype.getChildAt\r
+ * @param {number} index 取得する子ノードの位置。0~\r
+ * @return {Node} 子要素\r
+ * @example child1 = parent.getChildAt(1);\r
  */\r
 function X_Node_getChildAt( i ){\r
        var xnodes = this[ '_xnodes' ];\r
        return xnodes && 0 <= i && i < xnodes.length && xnodes[ i ];\r
 };\r
 \r
-function X_Node_length(){\r
+/**\r
+ * 子要素の数を取得する。\r
+ * @alias Node.prototype.numChildren\r
+ * @return {number} 子要素の数。\r
+ * @example n = parent.numChildren();\r
+ */\r
+function X_Node_numChildren(){\r
        var xnodes = this[ '_xnodes' ];\r
        return xnodes ? xnodes.length : 0;\r
 };\r
 \r
-/* --------------------------------------\r
- *  firstChild, lastChild\r
+/**\r
+ * 最初の子要素を取得する。\r
+ * @alias Node.prototype.firstChild\r
+ * @return {Node} 最初の子要素\r
+ * @example child0 = parent.firstChild();\r
  */\r
 function X_Node_firstChild(){\r
        return this[ '_xnodes' ] && this[ '_xnodes' ][ 0 ];\r
 };\r
+\r
+/**\r
+ * 最後の子要素を取得する。\r
+ * @alias Node.prototype.lastChild\r
+ * @return {Node} 最後の子要素\r
+ * @example lastChild = parent.lastChild();\r
+ */\r
 function X_Node_lastChild(){\r
        var xnodes = this[ '_xnodes' ];\r
        return xnodes && xnodes[ xnodes.length - 1 ];\r
 };\r
 \r
-/* --------------------------------------\r
- *  getOrder\r
+/**\r
+ * 要素の index 位置を取得する。\r
+ * @alias Node.prototype.getOrder\r
+ * @return {number} index -1 の場合、親を持たない。\r
+ * @example index = node.getOrder();\r
  */\r
 function X_Node_getOrder(){\r
        var parent = this.parent;\r
-       if( !parent ) return -1;\r
-       return parent[ '_xnodes' ].indexOf( this );\r
+       return this === X_Node_html ?\r
+                               0 :\r
+                  parent ?\r
+                               parent[ '_xnodes' ].indexOf( this ) :\r
+                               -1;\r
 };\r
 \r
-/* --------------------------------------\r
- *  className, addClass, removeClass, hasClass\r
+/**\r
+ * className の取得と設定。\r
+ * @alias Node.prototype.className\r
+ * @return {string|Node} getter の場合 class 文字列、setter の場合自身。\r
+ * @example // getter\r
+ * className = node.className();\r
+ * // setter\r
+ * node.className( 'myClass myClass_new' );\r
  */\r
 function X_Node_className( v ){\r
        var node, _, __;\r
@@ -960,9 +1003,18 @@ function X_Node_className( v ){
        this[ '_flags' ] & X_Node_State.IN_TREE && X_Node_reserveUpdate();\r
        return this;\r
 };\r
+\r
+/**\r
+ * className の追加。\r
+ * @alias Node.prototype.addClass\r
+ * @param {string} className スペース区切りで複数のクラスを追加できる。\r
+ * @return {Node} 自身。\r
+ * @example node.addClass( 'myClass myClass_new' );\r
+ */\r
 function X_Node_addClass( v ){\r
-       var names = v.split( ' ' ),\r
-               i     = names.length,\r
+       var names  = v.split( ' ' ),\r
+               i      = names.length,\r
+               _class = this[ '_className' ],\r
                name;\r
        v = '';\r
        for( ; i; ){\r
@@ -970,18 +1022,27 @@ function X_Node_addClass( v ){
                if( !name ) continue;\r
                !this[ 'hasClass' ]( name ) && ( v += ( v ? ' ' : '' ) + name );\r
        };\r
-       return v ? this[ 'className' ]( this[ '_className' ] + ( this[ '_className' ] ? ' ' : '' ) + v ) : this;\r
+       return v ? this[ 'className' ]( ( _class ? _class + ' ' : '' ) + v ) : this;\r
 };\r
+\r
+/**\r
+ * className の削除。\r
+ * @alias Node.prototype.removeClass\r
+ * @param {string} className スペース区切りで複数のクラスを削除できる。\r
+ * @return {Node} 自身。\r
+ * @example node.removeClass( 'myClass myClass_new' );\r
+ */\r
 function X_Node_removeClass( v ){\r
-       var _          = ' ',\r
-               className  = this[ '_className' ],\r
-               names      = v.split( _ ),\r
+       var _      = ' ',\r
+               _class = this[ '_className' ],\r
+               names  = v.split( _ ),\r
                classNames, i, f, j;\r
-       if( !className ) return this;\r
-       for( classNames = className.split( _ ), i = classNames.length; i; ){\r
-               className = classNames[ --i ];\r
+\r
+       if( !_class ) return this;\r
+       for( classNames = _class.split( _ ), i = classNames.length; i; ){\r
+               _class = classNames[ --i ];\r
                for( j = names.length; j; ){\r
-                       if( className === names[ --j ] ){\r
+                       if( _class === names[ --j ] ){\r
                                classNames.splice( i, 1 );\r
                                names.splice( j, 1 );\r
                                f = true;\r
@@ -991,10 +1052,19 @@ function X_Node_removeClass( v ){
        };\r
        return f ? this[ 'className' ]( classNames.join( _ ) ) : this;\r
 };\r
+\r
+/**\r
+ * className の更新。\r
+ * @alias Node.prototype.toggleClass\r
+ * @param {string} className スペース区切りで複数のクラスを削除できる。\r
+ * @param {boolean} [opt_toggle=] true はクラスの追加。false はクラスの削除。undefined はクラスのトグル。\r
+ * @return {Node} 自身。\r
+ * @example node.toggleClass( 'myClass myClass_new', !!n );\r
+ */\r
 function X_Node_toggleClass( v, opt_toggle ){\r
        var names, i, name;\r
        if( opt_toggle !== undefined ){\r
-               return !!opt_toggle ? this[ 'addClass' ]( v ) : this[ 'removeClass' ]( v );     \r
+               return !opt_toggle ? this[ 'removeClass' ]( v ) : this[ 'addClass' ]( v );      \r
        };\r
        names = v.split( ' ' );\r
        for( i = names.length; i; ){\r
@@ -1003,28 +1073,38 @@ function X_Node_toggleClass( v, opt_toggle ){
        };\r
        return this;\r
 };\r
+\r
+/**\r
+ * className を持つか。\r
+ * @alias Node.prototype.hasClass\r
+ * @param {string} className スペース区切りで複数のクラスを削除できる。\r
+ * @return {boolean} \r
+ * @example node.hasClass( 'myClass myClass_new' );\r
+ */\r
 function X_Node_hasClass( v ){\r
        var _ = ' ',\r
-               className = this[ '_className' ],\r
+               _class = this[ '_className' ],\r
                i, name;\r
-       if( className === v ) return true;\r
-       if( !className ) return false;\r
+       if( _class === v ) return true;\r
+       if( !_class ) return false;\r
        \r
-       className = _ + className + _;\r
-       if( className.indexOf( _ + v + _ ) !== -1 ) return true; // lucky hit\r
+       _class = _ + _class + _;\r
+       if( _class.indexOf( _ + v + _ ) !== -1 ) return true; // lucky hit\r
        \r
        for( v = v.split( _ ), i = v.length; i; ){\r
                name = v[ --i ];\r
                if( name === '' ) continue;\r
-               if( className.indexOf( _ + name + _ ) === -1 ) return false;\r
+               if( _class.indexOf( _ + name + _ ) === -1 ) return false;\r
        };\r
        return true;\r
 };\r
 \r
-/* --------------------------------------\r
- *  html, text\r
- * \r
- * outerHTML が欲しい場合は、xnode.call('outerHTML') とできる。\r
+/**\r
+ * innerHTML 取得・設定。outerHTML が欲しい場合は、xnode.call('outerHTML') とできる。\r
+ * @alias Node.prototype.html\r
+ * @param {string} [html=] html文字列\r
+ * @return {string|Node} \r
+ * @example node.html( '<img>' );\r
  */\r
 function X_Node_html( html ){\r
        var _ = '', q = '"', xnodes, n, i, l;\r
@@ -1065,6 +1145,13 @@ function X_Node_html( html ){
 /*\r
  * null が来たら '', 数値等が来たら文字列化\r
  */\r
+/**\r
+ * textContent 取得・設定。null が来たら '', 数値等が来たら文字列化\r
+ * @alias Node.prototype.text\r
+ * @param {string} [text=]\r
+ * @return {string|Node} \r
+ * @example node.text( 'Hello, world!' );\r
+ */\r
 function X_Node_text( text ){\r
        var xnodes, texts, i, l;\r
        // setter\r
@@ -1108,28 +1195,25 @@ function X_Node_text( text ){
 function X_Node_call( name /*, opt_args... */ ){\r
        var l = arguments.length - 1,\r
                raw, func, args, params, i;\r
-               \r
-       X_Node_updateTimerID && X_Node_startUpdate();\r
-       \r
+\r
        switch( name ){\r
                case 'nodeType' :\r
                        return this[ '_tag' ] ? 1 : 3;\r
-               case 'text' :\r
-                       return this[ 'text' ]();\r
-               case 'html' :\r
-               case 'innerHTML' :\r
-                       return this[ 'html' ]();\r
                case 'outerHTML' :\r
                        X_Node_outerXNode = X_Node_body; // == true ならなんでもよい。型を合わすために xbody にしている\r
                        v = this[ 'html' ]();\r
                        X_Node_outerXNode = null;\r
                        return v;\r
+               case 'treeIsDirty' :\r
+                       return !!X_Node_updateTimerID;\r
                case 'fontSize' :\r
                        return X_Node_CSS_getCharSize( this );\r
                case 'inGPU' :\r
                        return !!( this[ '_flags' ] & ( X_Node_State.GPU_NOW | X_Node_State.GPU_RELEASE_RESERVED ) );\r
        };\r
        \r
+       X_Node_updateTimerID && X_Node_startUpdate();\r
+       \r
        raw  = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );\r
        if( !raw ) return;\r
        \r
@@ -1240,6 +1324,8 @@ function X_Node_startUpdate( time ){
        if( time ){\r
                // X.Timer 経由でないと発火しない このイベントでサイズを取ると無限ループに\r
                X_System[ '_listeners' ] && X_System[ '_listeners' ][ X_EVENT_UPDATED ] && X_System[ 'dispatch' ]( X_EVENT_UPDATED );   \r
+       } else {\r
+               X_System[ '_listeners' ] && X_System[ '_listeners' ][ X_EVENT_UPDATED ] && X_System[ 'asyncDispatch' ]( X_EVENT_UPDATED );\r
        };\r
        \r
        X_ViewPort[ '_listeners' ] && X_ViewPort[ '_listeners' ][ X_EVENT_AFTER_UPDATE ] && X_ViewPort[ 'asyncDispatch' ]( X_EVENT_AFTER_UPDATE );\r
@@ -1272,13 +1358,12 @@ var X_Node__commitUpdate =
                        };\r
 \r
                        // 2. GPU解放予約\r
-                       // TODO もしかしたらこのタイミングで更新できるかも。\r
                        if( that[ '_flags' ] & X_Node_State.GPU_RELEASE_RESERVED ){\r
-                               console.log( 'GPU 解放 ' );\r
+                               // console.log( 'GPU 解放 ' );\r
                                //X_Node_updateReservedByReleaseGPU = true;\r
                                //X_Node__updateRawNode( that, elm );\r
                                that[ '_flags' ] &= X_Node_BitMask_RESET_GPU;\r
-                               //return elm;\r
+                               //return elm;// TODO もしかしたらこのタイミングで更新できるかも。\r
                        };\r
 \r
                        // 3. GPU予約 -> GPU\r