OSDN Git Service

Version 0.6.18, rewrite for async DOM update.
authoritozyun <itozyun@user.sourceforge.jp>
Sat, 15 Feb 2014 17:15:03 +0000 (02:15 +0900)
committeritozyun <itozyun@user.sourceforge.jp>
Sat, 15 Feb 2014 17:15:03 +0000 (02:15 +0900)
13 files changed:
0.6.x/index.html
0.6.x/js/core/00_X.js
0.6.x/js/dom/10_XDom.js
0.6.x/js/dom/11_XDomDTD.js [new file with mode: 0644]
0.6.x/js/dom/11_XDomNode.js
0.6.x/js/dom/12_XDomEvent.js
0.6.x/js/dom/13_XDomBoxModel.js
0.6.x/js/dom/14_XDomAttr.js
0.6.x/js/dom/15_XDomStyle.js
0.6.x/js/dom/17_XDomNodeList.js
0.6.x/js/dom/18_XDomQuery.js
0.6.x/js/dom/19_XDomParser.js
0.6.x/js/dom/20_XDomImage.js [new file with mode: 0644]

index 3bc212e..184a7db 100644 (file)
@@ -1,53 +1,56 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\r
 <html>\r
 <head>\r
-       <meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r
-       <meta http-equiv="Content-Language" content="ja">\r
-       <meta http-equiv="Content-Script-Type" content="text/javascript">\r
-       <meta http-equiv="Content-Style-Type" content="text/css">\r
-       <meta http-equiv="imagetoolbar" content="no">\r
-       <title>Js UI</title>\r
-       <link rel="stylesheet" type="text/css" media="all" href="css/ju.css">\r
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r
+<meta http-equiv="Content-Language" content="ja">\r
+<meta http-equiv="Content-Script-Type" content="text/javascript">\r
+<meta http-equiv="Content-Style-Type" content="text/css">\r
+<meta http-equiv="imagetoolbar" content="no">\r
+<title>Js UI</title>\r
+<link rel="stylesheet" type="text/css" media="all" href="css/ju.css">\r
+<link rel="stylesheet" type="text/css" media="all" href="css/tree.css">\r
 \r
-       <script type="text/javascript" src="js/core/00_builtin.js"></script>\r
-       <script type="text/javascript" src="js/core/00_X.js"></script>\r
-       <script type="text/javascript" src="js/core/01_XUa.js"></script>\r
-       <script type="text/javascript" src="js/core/02_XType.js"></script>\r
+<script type="text/javascript" src="js/core/00_builtin.js"></script>\r
+<script type="text/javascript" src="js/core/00_X.js"></script>\r
+<script type="text/javascript" src="js/core/01_XUa.js"></script>\r
+<script type="text/javascript" src="js/core/02_XType.js"></script>\r
 \r
-       <script type="text/javascript" src="js/core/03_XCallback.js"></script>\r
-       <script type="text/javascript" src="js/core/04_XClass.js"></script>\r
-       <script type="text/javascript" src="js/core/05_XTimer.js"></script>\r
-       <script type="text/javascript" src="js/core/06_XEventDispatcher.js"></script>\r
-       <script type="text/javascript" src="js/core/07_XNotification.js"></script>\r
+<script type="text/javascript" src="js/core/03_XCallback.js"></script>\r
+<script type="text/javascript" src="js/core/04_XClass.js"></script>\r
+<script type="text/javascript" src="js/core/05_XTimer.js"></script>\r
+<script type="text/javascript" src="js/core/06_XEventDispatcher.js"></script>\r
+<script type="text/javascript" src="js/core/07_XNotification.js"></script>\r
 \r
-       <script type="text/javascript" src="js/dom/10_XDom.js"></script>\r
-       <script type="text/javascript" src="js/dom/11_XDomNode.js"></script>\r
-       <script type="text/javascript" src="js/dom/12_XDomEvent.js"></script>\r
-       <script type="text/javascript" src="js/dom/13_XDomBoxModel.js"></script>\r
-       <script type="text/javascript" src="js/dom/14_XDomAttr.js"></script>\r
-       <script type="text/javascript" src="js/dom/15_XDomStyle.js"></script>\r
-       <!-- <script type="text/javascript" src="js/dom/16_XDomAnime.js"></script> -->\r
-       <script type="text/javascript" src="js/dom/17_XDomNodeList.js"></script>\r
-       <script type="text/javascript" src="js/dom/18_XDomQuery.js"></script>\r
-       <script type="text/javascript" src="js/dom/19_XDomParser.js"></script>\r
+<script type="text/javascript" src="js/dom/10_XDom.js"></script>\r
+<script type="text/javascript" src="js/dom/11_XDomDTD.js"></script>\r
+<script type="text/javascript" src="js/dom/11_XDomNode.js"></script>\r
+<script type="text/javascript" src="js/dom/12_XDomEvent.js"></script>\r
+<script type="text/javascript" src="js/dom/13_XDomBoxModel.js"></script>\r
+<script type="text/javascript" src="js/dom/14_XDomAttr.js"></script>\r
+<script type="text/javascript" src="js/dom/15_XDomStyle.js"></script>\r
+<!-- <script type="text/javascript" src="js/dom/16_XDomAnime.js"></script> -->\r
+<script type="text/javascript" src="js/dom/17_XDomNodeList.js"></script>\r
+<script type="text/javascript" src="js/dom/18_XDomQuery.js"></script>\r
+<script type="text/javascript" src="js/dom/19_XDomParser.js"></script>\r
 \r
 \r
-       <script type="text/javascript" src="js/ui/00_XUI.js"></script>\r
-       <script type="text/javascript" src="js/ui/04_XUI_Event.js"></script>\r
+<script type="text/javascript" src="js/ui/00_XUI.js"></script>\r
+<script type="text/javascript" src="js/ui/04_XUI_Event.js"></script>\r
+\r
+<script type="text/javascript" src="js/ui/05_XUI_Gesture.js"></script>\r
+<script type="text/javascript" src="js/ui/AbstractDisplayNode.js"></script>\r
+<script type="text/javascript" src="js/ui/AbstractDisplayContainer.js"></script>\r
+<script type="text/javascript" src="js/ui/DisplayNodeStyle.js"></script>\r
+<script type="text/javascript" src="js/ui/LayoutManagerBase.js"></script>\r
+<script type="text/javascript" src="js/ui/Box.js"></script>\r
+<script type="text/javascript" src="js/ui/VBox.js"></script>\r
+<script type="text/javascript" src="js/ui/HBox.js"></script>\r
+<script type="text/javascript" src="js/ui/TileBox.js"></script>\r
+<script type="text/javascript" src="js/ui/ChromeBox.js"></script>\r
+<script type="text/javascript" src="js/ui/ScrollBox.js"></script>\r
+<script type="text/javascript" src="js/ui/PageRoot.js"></script>\r
+<script type="text/javascript" src="js/ui/Text.js"></script>\r
 \r
-       <script type="text/javascript" src="js/ui/05_XUI_Gesture.js"></script>\r
-       <script type="text/javascript" src="js/ui/AbstractDisplayNode.js"></script>\r
-       <script type="text/javascript" src="js/ui/AbstractDisplayContainer.js"></script>\r
-       <script type="text/javascript" src="js/ui/DisplayNodeStyle.js"></script>\r
-       <script type="text/javascript" src="js/ui/LayoutManagerBase.js"></script>\r
-       <script type="text/javascript" src="js/ui/Box.js"></script>\r
-       <script type="text/javascript" src="js/ui/VBox.js"></script>\r
-       <script type="text/javascript" src="js/ui/HBox.js"></script>\r
-       <script type="text/javascript" src="js/ui/TileBox.js"></script>\r
-       <script type="text/javascript" src="js/ui/ChromeBox.js"></script>\r
-       <script type="text/javascript" src="js/ui/ScrollBox.js"></script>\r
-       <script type="text/javascript" src="js/ui/PageRoot.js"></script>\r
-       <script type="text/javascript" src="js/ui/Text.js"></script>\r
 </head>\r
 <body></body>\r
 </html>
\ No newline at end of file
index 93757f8..5d5f0b2 100644 (file)
@@ -1,66 +1,83 @@
-if( !window['console'] ) console = { log : function(a){alert(a)} };\r
+if( !window['console'] ) console = { log : function(a){\r
+       //alert(a)\r
+} };\r
 \r
 var undefined,\r
-       X = X || {\r
-               \r
-               VERSION : '0.6.17',\r
+       X = X || new Function( 'return X._shortcut && X._shortcut.apply( X._shortcut, arguments )' );\r
+\r
+X.VERSION = '0.6.18';\r
                \r
-               bootTime : + new Date,\r
+X.bootTime = + new Date;\r
                \r
-               getTime : Date.now ? new Function( 'return Date.now()' ) : new Function( 'return +new Date' ),\r
+X.getTime = Date.now ? new Function( 'return Date.now()' ) : new Function( 'return +new Date' );\r
                \r
-               emptyFunction : new Function,\r
+X.emptyFunction = new Function;\r
                \r
                // defer の場合もあるので、document.readyState を見る\r
-               inHead        : (function( s ){\r
-                       if( !s ) return;\r
-                       s = s[ s.length - 1 ];\r
-                       // Dom0 || Dom1\r
-                       return ( s.parentElement || s.parentNode ).tagName.toLowerCase() === 'head';\r
-               })( document.scripts || document.getElementsByTagName && document.getElementsByTagName( 'script' ) || document.all && document.all.tags( 'script' ) ),\r
+X.inHead = (function( s ){\r
+       if( !s ) return false;\r
+       s = s[ s.length - 1 ];\r
+       // Dom0 || Dom1\r
+       return ( s.parentElement || s.parentNode ).tagName.toLowerCase() === 'head';\r
+})( document.scripts || document.getElementsByTagName && document.getElementsByTagName( 'script' ) || document.all && document.all.tags( 'script' ) );\r
 \r
-               parse : function( v ){\r
-                       var _v, n;\r
-                       if( Type.isString( v ) === true ){\r
-                               switch( v ){\r
-                                       case ''          : return v;\r
-                                       //case '{}'        : return {};\r
-                                       //case '[]'        : return [];\r
-                                       case 'NaN'       : return NaN;\r
-                                       case 'null'      : return null;\r
-                                       case 'true'      : return true;\r
-                                       case 'false'     : return false;\r
-                                       case 'Infinity'  : return Number.POSITIVE_INFINITY;\r
-                                       case '-Infinity' : return Number.NEGATIVE_INFINITY;     \r
-                                       case 'undefined' : return;\r
-                               };\r
-                               _v = v.split( ' ' ).join( '' );\r
-                               n  = _v - 0;\r
-                               if( '' + n === _v || '' + n === '0' + _v  ) return n;\r
-                       };\r
-                       return v;\r
-               },\r
-               \r
-               isEmptyObject : function( v ){\r
-                       if( v.length !== 0 ) return false;\r
-                       for( var p in v ){\r
-                               if( v.hasOwnProperty( p ) ) return false;\r
-                       };\r
-                       return true;\r
-               },\r
+X.parse = function( v ){\r
+       var _v, n;\r
+       if( Type.isString( v ) === true ){\r
+               switch( v ){\r
+                       case ''          : return v;\r
+                       //case '{}'        : return {};\r
+                       //case '[]'        : return [];\r
+                       case 'NaN'       : return NaN;\r
+                       case 'null'      : return null;\r
+                       case 'true'      : return true;\r
+                       case 'false'     : return false;\r
+                       case 'Infinity'  : return Number.POSITIVE_INFINITY;\r
+                       case '-Infinity' : return Number.NEGATIVE_INFINITY;     \r
+                       case 'undefined' : return;\r
+               };\r
+               _v = v.split( ' ' ).join( '' );\r
+               n  = _v - 0;\r
+               if( '' + n === _v || '' + n === '0' + _v  ) return n;\r
+       };\r
+       return v;\r
+};\r
                \r
-               matchTest : function( array1, array2 ){\r
-                       var i = array2.length;\r
-                       for( ; i; ){\r
-                               if( array1.indexOf( array2[ --i ] ) === -1 ) return false;\r
-                       };\r
-                       return true;\r
-               },\r
+X.cloneObject = function( src ){\r
+       var ret, k;\r
+       if( typeof src !== 'object' ) return src;\r
+       ret = {};\r
+       for( k in src ){\r
+               ret[ k ] = src[ k ];\r
+       };\r
+       return ret;\r
+};\r
+\r
+X.copyArray = function( ary ){\r
+       var ret = [], i = ary.length;\r
+       if( !i ) return ret;\r
+       for( ; i; ){\r
+               ret[ --i ] = ary[ i ];\r
+       };\r
+       return ret;\r
+};\r
+       \r
+X.isEmptyObject = function( v ){\r
+       if( v.length !== 0 ) return false;\r
+       for( var p in v ){\r
+               if( v.hasOwnProperty( p ) ) return false;\r
+       };\r
+       return true;\r
+};\r
                \r
-               findFromArray : function( fakeArray, elm ){\r
-                       \r
-               }\r
+X.matchTest = function( array1, array2 ){\r
+       var i = array2.length;\r
+       for( ; i; ){\r
+               if( array1.indexOf( array2[ --i ] ) === -1 ) return false;\r
        };\r
+       return true;\r
+};\r
+\r
        \r
 // bonus: hotfix for IE6 SP1 (bug KB823727)\r
 document.execCommand && document.execCommand( 'BackgroundImageCache', false, true );\r
index d51ae76..7539b1e 100644 (file)
 \r
 })( window, document );\r
 \r
+X.Dom.cleanupTagNames     = 'noscript,noframes,comment,noembed,nolayer'.split( ',' );\r
 X.Dom.skipCleanupTagNames = 'pre,textarea,code,kbd,samp,xmp,plaintext,listing'.split( ',' );\r
                \r
 X.Dom.cleanupWhiteSpace = function( text ){\r
-       var _ = ' ', __ = '  ';\r
+       var _ = ' ', __ = '  ', c09 = String.fromCharCode( 9 ), c10 = String.fromCharCode( 10 );\r
        text.indexOf( '\r\n' ) !== -1 && ( text = text.split( '\r\n' ).join( _ ) );\r
        text.indexOf( '\n\r' ) !== -1 && ( text = text.split( '\n\r' ).join( _ ) );\r
        text.indexOf( '\t' )   !== -1 && ( text = text.split( '\t' ).join( _ ) );\r
@@ -125,12 +126,37 @@ X.Dom.cleanupWhiteSpace = function( text ){
        text.indexOf( '\n' )   !== -1 && ( text = text.split( '\n' ).join( _ ) );\r
        text.indexOf( '\f' )   !== -1 && ( text = text.split( '\f' ).join( _ ) );\r
        text.indexOf( '\b' )   !== -1 && ( text = text.split( '\b' ).join( _ ) );\r
+       text.indexOf( c09 )    !== -1 && ( text = text.split( c09 ).join( _ ) );\r
+       text.indexOf( c10 )    !== -1 && ( text = text.split( c10 ).join( _ ) );\r
        while( text.indexOf( __ ) !== -1 ){\r
                text = text.split( __ ).join( _ );\r
        };\r
        return text;\r
 };\r
 \r
+X.Dom.whiteSpaceToTag = function( text ){\r
+    if( text == null ) return '';\r
+    return text.toString()\r
+       .split( '\r\n\r\n' ).join( '<br>' )\r
+       .split( '\n\r\n\r' ).join( '<br>' )\r
+       .split( '\r\n' ).join( '<br>' )\r
+       .split( '\n\r' ).join( '<br>' )\r
+       .split( '\r' ).join( '<br>' )\r
+       .split( '\n' ).join( '<br>' )\r
+       .split( '\t' ).join( '' )\r
+       .split( '\f' ).join( '' )\r
+       .split( '\b' ).join( '' );\r
+};\r
+\r
+X.Dom.chrReferanceTo = function( str ){\r
+    if( str == null ) return '';\r
+    return str.toString()\r
+       .split( '&amp;' ).join( '&' )\r
+       .split( '&lt;' ).join( '<' )\r
+       .split( '&gt;' ).join( '>' )\r
+       .split( '&nbsp;' ).join( ' ' );\r
+};\r
+\r
 /*\r
  * original\r
  * AS3で相対パスを絶対パスに変換する\r
@@ -170,12 +196,3 @@ X.Dom.getAbsolutePath = function( path ){
        return [ _ary[ 0 ], ss, ary.join( s ), s, path ].join( '' );\r
 };\r
 \r
-\r
-X.Dom.Dirty = {\r
-       CLEAN     :  0,\r
-       TREE      :  1, // width, height, x, y\r
-       CONTENT   :  2,  // width, height, x, y textNode の内容\r
-       CLASSNAME :  4, // _getCharSize, width, height, x, y\r
-       CSS       :  8, // _getCharSize, width, height, x, y\r
-       ATTR      : 16  // _getCharSize, width, height, x, y\r
-};
\ No newline at end of file
diff --git a/0.6.x/js/dom/11_XDomDTD.js b/0.6.x/js/dom/11_XDomDTD.js
new file mode 100644 (file)
index 0000000..bdb2854
--- /dev/null
@@ -0,0 +1,4 @@
+\r
+X.Dom.DTD = {\r
+       EMPTY : {area:1,base:1,basefont:1,br:1,col:1,frame:1,hr:1,img:1,input:1,isindex:1,link:1,meta:1,param:1,embed:1}\r
+};\r
index cf650fb..4505d75 100644 (file)
@@ -1,4 +1,14 @@
 \r
+X.Dom.Dirty = {\r
+       CLEAN            :  0,\r
+       TREE             :  1, // width, height, x, y\r
+       CONTENT          :  2,  // width, height, x, y textNode の内容\r
+       CLASSNAME        :  4, // _getCharSize, width, height, x, y\r
+       CSS              :  8, // _getCharSize, width, height, x, y\r
+       ATTR             : 16,  // _getCharSize, width, height, x, y\r
+       IE4_TEXTNODE_FIX : 32\r
+};\r
+\r
 /*\r
  * Node( rawElement | rawTextnode | htmlString | textString )\r
  */\r
@@ -8,8 +18,13 @@ X.Dom.Node = X.EventDispatcher.inherits(
        X.Class.POOL_OBJECT,\r
        {\r
                _uid       : 0,\r
-               _rawNode   : null,              \r
-               parent     : null,              \r
+               _state     : 0,\r
+               _destroyed : false,\r
+               _dirty     : 0,         \r
+               \r
+               _rawNode   : null,\r
+               _root      : null,              \r
+               parent     : null,\r
                _xnodes    : null,\r
        \r
                _xnodeType : 0,\r
@@ -17,14 +32,13 @@ X.Dom.Node = X.EventDispatcher.inherits(
                _text      : null,\r
                _id        : null,\r
                _className : '',\r
-               _classText : ' ',\r
 \r
                _attrs     : null, // X.Dom.Attr\r
+               _newAttrs  : null,\r
                _attrText  : '',\r
-               _attrUpdated : false,\r
+               \r
                _css       : null, // X.Dom.Style\r
                _cssText   : '',\r
-               _styleText : '',\r
                \r
                Constructor : function( v ){\r
                        var css, xnodes, xnode, parent, uid = Node._chashe.length;\r
@@ -41,6 +55,10 @@ X.Dom.Node = X.EventDispatcher.inherits(
                                Node._newByText = false;\r
                                this._text      = v;\r
                                this._xnodeType = 3;\r
+                               this._charCode  = '';\r
+                               for( v = 0; v < this._text.length; ++v ){\r
+                                       this._charCode += this._text.charCodeAt( v ) + ',';\r
+                               };\r
                        } else {\r
                                if( 1 < arguments.length ) return new X.Dom.NodeList( arguments );\r
                                if( X.Type.isArray( v ) && v.length ) return new X.Dom.NodeList( v );\r
@@ -54,12 +72,12 @@ X.Dom.Node = X.EventDispatcher.inherits(
                                                if( xnode = Node._getXNode( v ) ) return xnode;\r
                                                // v.parentNode || v.parentElement : dom1 || dom0\r
                                                this.parent     = v !== document.body && ( parent = v.parentNode || v.parentElement ) && parent.tagName /* ie7- */ && Node._getXNode( parent );\r
+                                               this._state     = this.parent ? Node.STATE_STAGED : Node.STATE_NO_PARENT;\r
                                                this._rawNode   = v;\r
                                                this._xnodeType = 1;\r
                                                this._tag       = v.tagName;\r
                                                this._id        = v.id;\r
                                                this._className = v.className;\r
-                                               this._classText = ' class="' + this._className + '" ';\r
                                                this.cssText( v.style.cssText );\r
                                                // attr\r
                                                \r
@@ -73,20 +91,24 @@ X.Dom.Node = X.EventDispatcher.inherits(
                                        case Node.IS_RAW_TEXT :\r
                                                if( xnode = Node._getXNode( v ) ) return xnode;\r
                                                this.parent     = Node._getXNode( v.parentNode );\r
+                                               this._state     = this.parent ? Node.STATE_STAGED : Node.STATE_NO_PARENT;\r
                                                this._rawNode   = v;\r
                                                this._xnodeType = 3;\r
                                                this._text      = v.data;\r
+                                               v.UID = uid;\r
                                                break;\r
                                        case Node.IS_HTML_STRING :\r
                                        case Node.IS_STRING :\r
                                                if( xnodes = X.Dom.parse( v, true ) && 1 < xnodes.length ) return new X.Dom.NodeList( xnodes );\r
                                                if( xnodes.length ) return xnodes[ 0 ];\r
                                                return Node.none;\r
+                                       case Node.IS_IMAGE :\r
+                                               v.UID = uid;\r
                                        case Node.IS_WINDOW :\r
                                        case Node.IS_DOCUMENT :\r
-                                       case Node.IS_IMAGE :\r
                                                this._rawNode   = v;\r
                                                this._xnodeType = 2;\r
+                                               this._state     = Node.STATE_STAGED;\r
                                                break;\r
                                        default :\r
                                                if( Node.none ) return Node.none;\r
@@ -99,19 +121,28 @@ X.Dom.Node = X.EventDispatcher.inherits(
        }\r
 );\r
 \r
-var Node = X.Dom.Node;\r
+var Node = X._shortcut = X.Dom.Node;\r
 \r
 Node.IS_XNODE       = 1;\r
 Node.IS_RAW_HTML    = 2;\r
 Node.IS_RAW_TEXT    = 3;\r
 Node.IS_HTML_STRING = 4;\r
 Node.IS_STRING      = 5;\r
-Node.IS_DOC_FRAG    = 6;\r
+//Node.IS_DOC_FRAG    = 6;\r
 Node.IS_XNODE_LIST  = 7;\r
 Node.IS_WINDOW      = 8;\r
 Node.IS_DOCUMENT    = 9;\r
 Node.IS_IMAGE       = 10;\r
 \r
+\r
+Node.STATE_NO_RAW    = 0; // new Node されたばかり\r
+Node.STATE_NO_PARENT = 1; // exist node._rawNode\r
+//Node.STATE_DIRTY     = 2;\r
+Node.STATE_STAGED    = 2; // exist _rawNode.parentNode\r
+Node.STATE_DESTROYED = 3;\r
+\r
+Node._useDocumentFragment = document.createDocumentFragment && ( !X.UA.IE || 6 <= X.UA.IE ) && document.createDocumentFragment();\r
+\r
 Node._getType = function( v ){\r
        if( v === '' ) return Node.IS_STRING;\r
        if( !v ) return 0;\r
@@ -125,17 +156,28 @@ Node._getType = function( v ){
        if( typeof v === 'string' ){\r
                return '<' === v.charAt( 0 ) && v.charAt( v.length - 1 ) === '>' ? Node.IS_HTML_STRING : Node.IS_STRING;\r
        };\r
-       if( v.nodeType === 11 ) return Node.IS_DOC_FRAG;\r
+       //if( v.nodeType === 11 ) return Node.IS_DOC_FRAG;\r
        return 0;\r
 };\r
 Node._getXNode = function( node ){\r
        var uid;\r
-       if( !node ) return;\r
-       if( X.UA.IE && X.UA.IE < 5 ){\r
-               uid = node.getAttribute( 'UID' );\r
-               return uid && Node._chashe[ uid ];\r
+       switch( Node._getType( node ) ){\r
+               case Node.IS_XNODE :\r
+               case Node.IS_XNODE_LIST :\r
+                       return node;\r
+               case Node.IS_RAW_HTML :\r
+               case Node.IS_RAW_TEXT :\r
+               case Node.IS_IMAGE :\r
+                       if( X.UA.IE && X.UA.IE < 5 ){\r
+                               uid = node.getAttribute( 'UID' );\r
+                               return uid && Node._chashe[ uid ];\r
+                       };\r
+                       return node.UID && Node._chashe[ node.UID ];\r
+               case Node.IS_WINDOW :\r
+                       return Node._window;\r
+               case Node.IS_DOCUMENT :\r
+                       return Node._document;\r
        };\r
-       return node.UID && Node._chashe[ node.UID ];\r
 };\r
 \r
 \r
@@ -161,34 +203,6 @@ Node.isXmlDocument =
                        return root._rawNode.createElement( 'p' ).tagName !== root._rawNode.createElement( 'P' ).tagName;\r
                });\r
 \r
-\r
-/* --------------------------------------\r
- *  Dom Core 1\r
- */\r
-if( document.getElementById ){\r
-       Node._dom1cleanUp = function( xnode ){\r
-               var elm      = xnode._rawNode,\r
-                       children = xnode._xnodes,\r
-                       childNodes, i, l, child, _child;\r
-               if( elm && children && ( childNodes = elm.childNodes ) ){\r
-                       for( i = 0, l = children.length; i < l; ++i ){\r
-                               child = children[ i ];\r
-                               if( child.constructor === Node ) child = child._create( true );\r
-                               if( typeof child === 'string'  ) child = document.createTextNode( child );\r
-                               if( ( _child = childNodes[ i ] ) !== child ){\r
-                                       _child ?\r
-                                               elm.insertBefore( child, _child ) :\r
-                                               elm.appendChild( child );\r
-                                       _child && elm.removeChild( _child );\r
-                               };\r
-                       };\r
-                       while( ( _child = childNodes[ i ] ) ){\r
-                               elm.removeChild( _child );\r
-                       };\r
-               };\r
-       };      \r
-};\r
-\r
 Node._chashe     = [];\r
 Node.none        = Node._chashe[ 0 ] = new Node();\r
 Node._window     = new Node( window ); // Node._chashe[ 1 ]\r
@@ -197,183 +211,36 @@ Node._html       = null; // Node._chashe[ 3 ]
 Node.root        = null;// = Node._chashe[ 4 ] body\r
 Node._systemNode = null;// = Node._chashe[ ? ]\r
 \r
-/* --------------------------------------\r
- *  Create\r
- */\r
-Node.prototype._create =\r
-       // document.createElement of ie4 is only for OPTION & IMAGE.\r
-       document.getElementById ? (function( isChild ){\r
-               var tag = this._tag, node, frg;\r
-/*\r
- * http://d.hatena.ne.jp/uupaa/20080718/1216362040\r
- * DOM Rangeが使える環境(Firefox2+,Opera9+,Safari3+)なら、innerHTMLいらずで、ガーって書けます。\r
- * return document.createRange().createContextualFragment("<div><select><option></option></select></div>");\r
- * \r
- * ie7 以下では iframe の frameborder や、input name は、createElement 後に aetAttribute しても無視される\r
- */\r
-\r
-               if( !( node = this._rawNode ) ){\r
-                       this._isNew = true;\r
-                       node = this._rawNode = (\r
-                               tag && X.UA.IE ?\r
-                                       document.createElement( [\r
-                                               '<', this._tag,\r
-                                                       ' UID="', this._uid, '"',\r
-                                                       this._id ? ' id="' + this._id + '"' : '',\r
-                                                       this._classText,\r
-                                                       ( this._attrUpdated ? ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ) : this._attrText ),\r
-                                                       this._styleText,\r
-                                               '>' ].join( '' ) ) :\r
-                               tag ?\r
-                                       document.createElement( tag ) :\r
-                                       document.createTextNode( this._text ) );\r
-                       delete this._attrUpdated;\r
-               };\r
-               // fragument がある場合 children も足して\r
-               // Mozilla: 1.0+, IE: 6.0+, Netscape: 2.0+, Safari: 1.0+, Opera: 7.0+\r
-               if( !isChild && document.createDocumentFragment ){\r
-                       if( node.nodeType === 1 ){\r
-                               frg = document.createDocumentFragment();\r
-                               frg.appendChild( node );\r
-                               Node._dom1cleanUp( this );\r
-                               return frg;\r
-                       };\r
-               };\r
-               \r
-               return node;\r
-       }) :\r
-       document.all ? (function( skipRemove, skipContainsDirty ){\r
-               var html, attrs, attr, children, i, l, child, toName, noValue, name;\r
-               if( this._xnodeType !== 1 ) return this._text;\r
-               \r
-               if( this._rawNode || this._ie4getRawNode() ){\r
-                       if( skipRemove ){\r
-                               this._beforeRemove();\r
-                       } else {\r
-                               // 追加する前に要素を抜く\r
-                               this.remove();          \r
-                       };\r
-                       if( !skipContainsDirty && !this._ie4containsDirty() ){\r
-                               return this._htmlText;\r
-                       };\r
-               };\r
-               html = [\r
-                       '<', this._tag, ' id=', ( this._id || ( 'ie4uid' + this._uid ) ),\r
-                       this._classText,\r
-                       ( this._attrUpdated ? ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ) : this._attrText ),\r
-                       this._styleText,\r
-               '>' ];\r
-               delete this._attrUpdated;\r
-               \r
-               if( ( children = this._xnodes ) && ( l = children.length ) ){\r
-                       for( i = 0; i < l; ++i ){\r
-                               html[ html.length ] = children[ i ]._create( true, true );\r
-                       };\r
-               };\r
-               html[ html.length ] = '<\/' + this._tag + '>';\r
-               return html.join( '' );\r
-       }) :\r
-       (function(){});\r
+Node._reserveRemoval = [];\r
 \r
-Node.prototype._afterCreate =\r
-       ( document.getElementById ) ? (function( parent ){\r
-               var _children = this._xnodes,\r
-                       node      = this._rawNode,\r
-                       eChildren = node && node.nodeType === 1 && node.childNodes,\r
-                       attrs, p, _child, i, l;\r
-               this.parent = parent;\r
-               if( this._xnodeType !== 1 ) return this;\r
-               if( this._isNew ){\r
-                       if( _children && !document.createDocumentFragment ){\r
-                               Node._dom1cleanUp( this ); // docFrg が使えない場合、doc 追加後に子を追加\r
-                       };\r
-                       if( !X.UA.IE ){\r
-                               node.UID       = this._uid;\r
-                               if( this._id ) node.id = this._id;\r
-                               if( this._className ) node.className = this._className;\r
-                               // ie では createElement に <div class=...> HTML 文字列を渡すことができる\r
-                               // 動的に生成した iframe に後から frameborder 等を設定しても無視される ie7\r
-                               if( attrs = this._attrs ){\r
-                                       for( p in attrs ){\r
-                                               node[ p ] = attrs[ p ];\r
-                                       };\r
-                               };\r
-                               node.style.cssText = this._cssText;                             \r
-                       };\r
-                       this._restoreEvent();// イベントの復帰\r
-                       delete this._isNew;\r
+if( !document.getElementById && document.all ){\r
+       Node.prototype._ie4getRawNode = function(){\r
+               var elm, uid;\r
+               if( elm = this._rawNode ) return elm;\r
+               if( this._id && ( elm = this._rawNode = document.all[ this._id ] ) ){\r
+                       return elm;\r
                };\r
-               /*\r
-                * elm.childNodes を this._xnodes にリンクさせる\r
-                */\r
-               if( _children ){\r
-                       for( i = 0, l = _children.length; i < l; ++i ){\r
-                               _child = _children[ i ];\r
-                               _child.constructor === Node ? _child._afterCreate( this ) : ( _children[ i ] = eChildren[ i ] );\r
-                       };\r
-               } else\r
-               if( eChildren && eChildren.length ){\r
-                       this._xnodes = [];\r
-                       this._xnodes.push.apply( this._xnodes, eChildren );\r
+               if( elm = this._rawNode = document.all[ 'ie4uid' + this._uid ] ){\r
+                       if( this._id ) elm.setAttribute( 'id', this._id );\r
+                       return elm;\r
                };\r
-               return this;\r
-       }) :\r
-       document.all ? (function( parent ){\r
-               var elm,\r
-                       children = this._xnodes,\r
-                       child, i, l;\r
-               this.parent = parent;\r
-               delete this._ie4dirty;\r
-               \r
-               if( this._xnodeType !== 1 ) return this;\r
+       };\r
+};\r
 \r
-               delete this._rawNode;\r
-               delete this._ie4dirtyChildren;\r
-               \r
-               if( children ){\r
-                       for( i = children.length; i; ){\r
-                               children[ --i ]._afterCreate( this );\r
-                       };\r
-               };\r
-               if( elm = this._ie4getRawNode() ){\r
-                       this._restoreEvent();// イベントの復帰\r
-                       elm.setAttribute( 'UID', '' + this._uid );\r
-               };\r
-       }) :\r
-       (function(){});\r
 \r
 /* --------------------------------------\r
  *  Create\r
  */\r
 Node.prototype.create = function( tag, opt_attrs, opt_css ){\r
-       var elm, xnode;\r
+       var xnode;\r
        if( this._xnodeType !== 1 ) return;\r
        if( !this._xnodes ) this._xnodes = [];\r
        \r
-       elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
-       \r
-       if( elm && !Node.skipCreate ){\r
-               if( document.getElementById ){\r
-                       // ie では iframe の frameborder が無視されるので、<iframe class=> を渡す\r
-                       elm.appendChild( document.createElement( tag ) );\r
-                       xnode = new Node( elm.lastChild );\r
-                       opt_attrs && xnode.attr( opt_attrs );\r
-                       opt_css   && xnode[ X.Type.isString( opt_css ) ? 'cssText' : 'css' ]( opt_css );\r
-               } else\r
-               if( document.all ){\r
-                       Node._newByTag = true;\r
-                       xnode = new Node( tag, opt_attrs, opt_css );\r
-                       // opt_attrs && xnode.attr( opt_attrs );\r
-                       elm.insertAdjacentHTML( 'BeforeEnd', xnode._create() );\r
-                       xnode._rawNode = elm.children[ elm.children.length - 1 ];\r
-               } else {\r
-                       \r
-               };\r
-       } else {\r
-               Node._newByTag = true;\r
-               xnode = new Node( tag, opt_attrs, opt_css );\r
-       };\r
+       Node._newByTag = true;\r
+       xnode = new Node( tag, opt_attrs, opt_css );\r
        xnode.parent = this;\r
+       \r
+       this._reserveUpdate();\r
        this._xnodes[ this._xnodes.length ] = xnode;\r
        return xnode;\r
 };\r
@@ -382,29 +249,15 @@ Node.prototype.create = function( tag, opt_attrs, opt_css ){
  *  CreateText\r
  */\r
 Node.prototype.createText = function( text ){\r
-       var elm, xnode;\r
+       var xnode;\r
        if( this._xnodeType !== 1 ) return;\r
        if( !this._xnodes ) this._xnodes = [];\r
        \r
-       elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
-       \r
-       if( elm && !Node.skipCreate ){\r
-               if( document.createTextNode ){\r
-                       elm.appendChild( document.createTextNode( text ) );\r
-                       xnode = new Node( elm.lastChild );\r
-               } else\r
-               if( document.all ){\r
-                       elm.insertAdjacentText( 'BeforeEnd', text );\r
-                       Node._newByText = true;\r
-                       xnode = new Node( text );\r
-               } else {\r
-                       \r
-               };\r
-       } else {\r
-               Node._newByText = true;\r
-               xnode = new Node( text );\r
-       };\r
+       Node._newByText = true;\r
+       xnode = new Node( text );\r
        xnode.parent = this;\r
+       \r
+       this._reserveUpdate();\r
        this._xnodes[ this._xnodes.length ] = xnode;\r
        return xnode;\r
 };\r
@@ -415,24 +268,17 @@ Node.prototype.createText = function( text ){
  * http://d.hatena.ne.jp/uupaa/20100508/1273299874\r
  */\r
 Node.prototype.clone = function( opt_clone_children ){\r
-       var xnode, elm;\r
+       var xnode, xnodes, i, l;\r
        switch( this._xnodeType ){\r
                case 1 :\r
-                       if( X.UA.IE && X.UA.IE < 5 ){\r
-                               \r
-                       } else\r
-                       if( X.UA.IE && 5 <= X.UA.IE && X.UA.IE < 10 ){\r
-                               Node._newByTag = true;\r
-                               xnode = new Node( this._tag, this._attrs, this._css );\r
-                               xnode.className( this.className() );\r
-                               if( opt_clone_children ){\r
-                                       \r
+                       Node._newByTag = true;\r
+                       xnode = new Node( this._tag, X.cloneObject( this._attrs ), X.cloneObject( this._css ) );\r
+                       xnode.className( this._className );\r
+                       if( opt_clone_children && ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
+                               for( i = 0; i < l; ++i ){\r
+                                       xnode.append( xnodes[ i ].clone( true ) );\r
                                };\r
-                       } else\r
-                       if( elm = this.rawNode ){\r
-                               xnode = new Node( elm.cloneNode( !!opt_clone_children ) );\r
                        };\r
-\r
                        return xnode;\r
                case 3 :\r
                        Node._newByText = true;\r
@@ -451,83 +297,59 @@ Node.prototype.clone = function( opt_clone_children ){
  * HtmlElement の場合は内部使用専用 そのため event の破棄等しない\r
  */\r
 Node.prototype.append = function( v ){\r
-       var elm, i, l, children, frg;\r
+       var i, l, xnodes, frg;\r
        if( this._xnodeType !== 1 ) return;\r
        \r
        if( 1 < ( l = arguments.length ) ){\r
-               if( document.createDocumentFragment && this._rawNode ){\r
-                       frg = document.createDocumentFragment();\r
-                       for( i = 0; i < l; ++i ){\r
-                               v = arguments[ i ];\r
-                               v = v.constructor === Node ? v : new Node( v );\r
-                               frg.appendChild( v._create() );\r
-                               this._xnodes[ this._xnodes.length ] = v;\r
-                               v._afterCreate( this );\r
-                       };\r
-                       this._rawNode.appendChild( frg );\r
-                       return this;\r
-               } else {\r
-                       for( i = 0; i < l; ++i ){\r
-                               this.append( arguments[ i ] );\r
-                       };\r
+               for( i = 0; i < l; ++i ){\r
+                       this.append( arguments[ i ] );\r
                };\r
                return this;\r
        };\r
        \r
-       if( !this._xnodes ) this._xnodes = [];\r
+       if( !( xnodes = this._xnodes ) ) this._xnodes = xnodes = [];\r
        \r
-       elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
        switch( Node._getType( v ) ){\r
                case Node.IS_RAW_HTML :\r
                case Node.IS_RAW_TEXT :\r
-                       if( elm ){\r
-                               if( document.getElementById ){\r
-                                       elm.appendChild( v );\r
-                               } else\r
-                               if( document.all ){\r
-                                       elm.insertAdjacentHTML( 'BeforeEnd', v.outerHTML );\r
-                                       v = elm.children[ elm.children.length - 1 ];\r
-                               } else {\r
-                                       \r
-                               };\r
-                       };\r
-                       this._xnodes[ this._xnodes.length ] = new Node( v );\r
+                       v = new Node( v );\r
                        break;\r
                case Node.IS_HTML_STRING :\r
                case Node.IS_STRING :\r
-                       this.append( X.Dom.parse( v, true ) );\r
-                       break;\r
+                       return this.append( X.Dom.parse( v, true ) );\r
                case Node.IS_XNODE :\r
-                       if( v === Node.none ) return this;\r
+                       if( v._xnodeType !== 1 && v._xnodeType !== 3 ) return this;\r
                        // 親の xnodes から v を消す\r
-                       v.parent && ( i = v.parent._xnodes.indexOf( v ) ) !== -1 && v.parent._xnodes.splice( i, 1 );\r
-                       if( elm ){\r
-                               if( document.getElementById ){\r
-                                       elm.appendChild( v._create() );\r
-                                       v._afterCreate( this );\r
-                               } else\r
-                               if( document.all ){\r
-                                       elm.insertAdjacentHTML( 'BeforeEnd', v._create() );\r
-                                       v._afterCreate( this );\r
-                               } else {\r
-                                       \r
-                               };\r
+                       if( v.parent ){\r
+                               v.parent._xnodes.splice( v.parent._xnodes.indexOf( v ), 1 );\r
+                               // ie4\r
+                               !document.getElementById && document.all && v.remove();\r
+                       } else\r
+                       if( ( i = Node._reserveRemoval.indexOf( v ) ) !== -1 ){\r
+                               if( v._destroyed ) alert( 'xnode already destroyed!' );\r
+                               Node._reserveRemoval.splice( i, 1 );\r
                        };\r
-                       this._xnodes[ this._xnodes.length ] = v;\r
+               default :\r
+                       return this;\r
        };\r
+\r
+       this._reserveUpdate();\r
+       v.parent = this;\r
+       v._state = Node.STATE_NO_PARENT;\r
+       xnodes[ xnodes.length ] = v;\r
        return this;\r
 };\r
 \r
 \r
 Node.prototype.appendAt = function( start, v ){\r
-       var children, l, elm, i, prev, next;\r
+       var xnodes, l, i;\r
        \r
        if( this._xnodeType !== 1 ) return this;\r
        \r
-       if( !( children = this._xnodes ) ) children = this._xnodes = [];\r
+       if( !( xnodes = this._xnodes ) ) xnodes = this._xnodes = [];\r
        \r
        l = arguments.length;\r
-       if( children.length <= start ){\r
+       if( xnodes.length <= start ){\r
                if( l === 2 ) return this.append( v );\r
                v = [];\r
                for( ; 1 < l; ){\r
@@ -537,90 +359,45 @@ Node.prototype.appendAt = function( start, v ){
        };\r
        if( start < 0 ) start = 0;\r
        if( 2 < l ){\r
-               if( document.createDocumentFragment && ( elm = this._rawNode ) ){\r
-                       var frg = document.createDocumentFragment();\r
-                       for( i = 0; i < l; ++i ){\r
-                               v = arguments[ i ];\r
-                               v = v.constructor === Node ? v : new Node( v );\r
-                               frg.appendChild( v._create() );\r
-                               children.splice( start + i, 0, v );\r
-                               v._afterCreate( this );\r
-                       };\r
-                       elm.insertBefore( frg, elm.childNodes[ start ] );\r
-                       return this;\r
-               };\r
                for( ; l; ){\r
                        this.appendAt( start, arguments[ --l ] );\r
                };\r
                return this;\r
        };\r
-       \r
-       if( !this.parent ){\r
-               children.splice( start, 0, v );\r
-               return this;\r
-       };\r
-       elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
+\r
        switch( Node._getType( v ) ){\r
                case Node.IS_RAW_HTML :\r
                case Node.IS_RAW_TEXT :\r
-                       if( elm ){\r
-                               if( document.getElementById ){\r
-                                       elm.insertBefore( v, elm.childNodes[ start ] );\r
-                               } else\r
-                               if( document.all ){\r
-                                       if( start === 0 ){\r
-                                               elm.insertAdjacentHTML( 'AfterBegin', v.outerHTML );\r
-                                               v = elm.children[ 0 ];\r
-                                       } else\r
-                                       if( ( next = children[ start ] ) && typeof next !== 'string' && next._xnodeType !== 3 &&\r
-                                               ( next = ( next._ie4getRawNode ? next._ie4getRawNode() : next ) ) ){\r
-                                               next.insertAdjacentHTML( 'BeforeBegin', v.outerHTML );\r
-                                               v = elm.children[ ( Array.prototype.indexOf.call( elm.children, next ) ) - 1 ];\r
-                                       } else\r
-                                       if( 0 < start && ( prev = children[ start - 1 ] ) && typeof prev !== 'string' && prev._xnodeType !== 3 &&\r
-                                               ( prev = ( prev._ie4getRawNode ? prev._ie4getRawNode() : prev ) ) ){\r
-                                               prev.insertAdjacentHTML( 'AfterEnd', v.outerHTML );\r
-                                               v = elm.children[ ( Array.prototype.indexOf.call( elm.children, prev ) ) + 1 ];\r
-                                       } else {\r
-                                               this._ie4reserveUpdate( v );// テキストノードの間に入れる場合!\r
-                                       };\r
-                               } else {\r
-                                       \r
-                               };\r
-                               children.splice( start, 0, v );\r
-                       } else {\r
-                               children.splice( start, 0, v );\r
-                       };\r
+                       v = new Node( v );\r
                        break;\r
                case Node.IS_HTML_STRING :\r
                case Node.IS_STRING :\r
                        v = X.Dom.parse( v, true );\r
-                       if( elm ){\r
-                               for( i = v.length; i; ){\r
-                                       this.appendAt( start, v[ --i ] );\r
-                               };\r
-                       } else\r
-                       if( v.length ){\r
-                               children.push.apply( children, v );\r
+                       for( i = v.length; i; ){\r
+                               this.appendAt( start, v[ --i ] );\r
                        };\r
-                       break;\r
+                       return this;\r
                case Node.IS_XNODE :\r
-                       if( v === Node.none ) return this;\r
+                       if( v._xnodeType !== 1 && v._xnodeType !== 3 ) return this;\r
                        // 親の xnodes から v を消す\r
-                       v.parent && ( i = v.parent._xnodes.indexOf( v ) ) !== -1 && v.parent._xnodes.splice( i, 1 );\r
-                       if( elm ){\r
-                               if( document.getElementById ){\r
-                                       elm.insertBefore( v._create(), elm.childNodes[ start ] );\r
-                                       v._afterCreate( this );\r
-                               } else\r
-                               if( document.all ){\r
-                                       this._ie4reserveUpdate( v );\r
-                               } else {\r
-                                       \r
-                               };\r
+                       if( v.parent ){\r
+                               v.parent._xnodes.splice( v.parent._xnodes.indexOf( v ), 1 );\r
+                               // ie4\r
+                               !document.getElementById && document.all && v.remove();\r
+                       } else\r
+                       if( ( i = Node._reserveRemoval.indexOf( v ) ) !== -1 ){\r
+                               if( v._destroyed ) alert( 'xnode already destroyed!' );\r
+                               Node._reserveRemoval.splice( i, 1 );\r
                        };\r
-                       children.splice( start, 0, v );\r
+                       break;\r
+               default :\r
+                       return this;\r
        };\r
+\r
+       this._reserveUpdate();\r
+       v.parent = this;\r
+       v._state = Node.STATE_NO_PARENT;\r
+       this._xnodes.splice( start, 0, v );\r
        return this;\r
 };\r
 \r
@@ -682,209 +459,65 @@ Node.prototype.replace = function( v ){
  *  Remove\r
  */\r
 Node.prototype.remove = function(){\r
-       var parent = this.parent, elm;\r
+       var parent = this.parent;\r
                \r
        if( !parent ) return this;\r
-       if( document.getElementById ){\r
-               if( this._rawNode ){\r
-                       this._xnodeType === 1 && this._beforeRemove();\r
-                       parent._rawNode.removeChild( this._rawNode );\r
-               };\r
-       } else\r
-       if( document.all ){\r
-               delete this._ie4dirty;\r
-               delete this._ie4dirtyChildren;\r
-               if( this._xnodeType === 1 ){\r
-                       this._beforeRemove();\r
-                       if( elm = this._ie4getRawNode() ){\r
-                               elm.outerHTML = '';\r
-                       };\r
-               } else {\r
-                       parent._beforeRemove(); //??\r
-                       parent._ie4reserveUpdate();\r
-               };\r
-       } else {\r
-               \r
-       };\r
 \r
+       this._state = Node.STATE_NO_PARENT;\r
        parent._xnodes.splice( parent._xnodes.indexOf( this ), 1 );\r
+       Node._reserveRemoval[ Node._reserveRemoval.length ] = this;\r
+       parent._reserveUpdate();\r
        delete this.parent;\r
        return this;\r
 };\r
 \r
-Node.prototype._beforeRemove = \r
-       document.getElementById ?\r
-               ( function(){\r
-                       var elm = this._rawNode, children,\r
-                               child, i, l;\r
-                       if( !elm ) return;\r
-                       this._migrateEvent();// イベントの退避\r
-                       if( children = this._xnodes ){\r
-                               for( i = 0, l = children.length; i < l; ++i ){\r
-                                       child = children[ i ];\r
-                                       child._xnodeType === 1 && child._beforeRemove();\r
-                               };\r
-                       };\r
-               }) :\r
-       document.all ? \r
-               ( function(){\r
-                       var elm = this._ie4getRawNode(),\r
-                               children, i, l;\r
-                       if( children = this._xnodes ){\r
-                               for( i = 0, l = children.length; i < l; ++i ){\r
-                                       children[ i ]._beforeRemove();\r
-                               };      \r
-                       };\r
-                       if( !elm ) return;\r
-                       this._migrateEvent();// イベントの退避\r
-                       this._htmlText = elm.outerHTML;\r
-                       elm.removeAttribute( 'id' );\r
-               }) :\r
-               (function(){});\r
-\r
-Node.prototype.empty =\r
-       document.getElementById ?\r
-               ( function(){\r
-                       var elm = this._rawNode, children,\r
-                               child, i, l;\r
-                       if( children = this._xnodes ){\r
-                               for( i = 0, l = children.length; i < l; ++i ){\r
-                                       children[ i ].destroy();\r
-                               };\r
-                               children.length = 0;\r
-                       };\r
-                       if( elm ) elm.innerHTML = '';\r
-                       return this;\r
-               }) :\r
-       document.all ? \r
-               ( function(){\r
-                       var elm = this._ie4getRawNode(),\r
-                               children, i, l;\r
-                       if( children = this._xnodes ){\r
-                               for( i = 0, l = children.length; i < l; ++i ){\r
-                                       children[ i ].destroy();\r
-                               };\r
-                               children.length = 0;\r
-                       };\r
-                       if( elm ) elm.innerHTML = '';\r
-                       return this;\r
-               }) :\r
-               (function(){});\r
-\r
-/* --------------------------------------\r
- *  destory\r
- */\r
-Node.prototype.destroy = function(){\r
-       var elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode,\r
-               children = this._xnodes, i, l;\r
-       \r
-       if( children ){\r
-               for( i = 0, l = children.length; i < l; ++i ){\r
-                       children[ i ].destroy();\r
+Node.prototype.empty = function(){\r
+       var xnodes = this._xnodes, child, i, l;\r
+       if( xnodes && ( l = xnodes.length ) ){\r
+               for( i = 0; i < l; ++i ){\r
+                       xnodes[ i ].destroy();\r
                };\r
-               children.length = 0;\r
-       };\r
-       this._xnodeType === 1 && this.unlisten(); // イベントの退避\r
-       if( elm ){\r
-               this._xnodeType === 1 && ( elm.innerHTML = '' );\r
-               // stop()\r
-               // remove() empty()\r
-               \r
-               document.getElementById && this.parent._rawNode.removeChild( elm );\r
+               xnodes.length = 0;\r
        };\r
-       delete Node._chashe[ this._uid ];\r
-       this.kill();\r
+       return this;\r
 };\r
 \r
 /* --------------------------------------\r
- *  for ie4\r
+ *  destory\r
  */\r
-if( !document.getElementById && document.all ){\r
-\r
-       Node.prototype._ie4getRawNode = function(){\r
-               var elm, uid;\r
-               if( elm = this._rawNode ) return elm;\r
-               if( this._id && ( elm = this._rawNode = document.all[ this._id ] ) ){\r
-                       return elm;\r
-               };\r
-               if( elm = this._rawNode = document.all[ 'ie4uid' + this._uid ] ){\r
-                       if( this._id ) elm.setAttribute( 'id', this._id );\r
-                       return elm;\r
-               };\r
-       };\r
+Node.prototype.destroy = function( isChild ){\r
+       var xnodes = this._xnodes, i;\r
        \r
-       Node.prototype._ie4reserveUpdate = function( child ){\r
-               var root = Node.root;\r
-               child && ( child._ie4dirty = true );\r
-               this._ie4dirtyChildren = true;\r
-               if( root._ie4reserved === true ) return;\r
-               root._ie4reserved = true;\r
-               X.Timer.once( 1, root, root._ie4startUpdate );\r
-       };\r
-       \r
-       Node.prototype._ie4startUpdate = function(){\r
-               if( this._ie4reserved !== true ) return;\r
-               delete this._ie4reserved;\r
-               if( !this._xnodes ) return;\r
-               this._ie4commitUpdate()._ie4afterUpdate();\r
-       };\r
-       \r
-       Node.prototype._ie4commitUpdate = function(){\r
-               var children = this._xnodes,\r
-                       i, l, html;\r
-               if( !this._ie4dirtyChildren ){\r
-                       if( children && ( l = children.length ) ){\r
-                               for( i = 0; i < l; ++i ){\r
-                                       children[ i ]._ie4commitUpdate();\r
-                               };                              \r
-                       };\r
-                       return this;\r
-               };\r
-               html = [];\r
-               if( children && ( l = children.length ) ){\r
-                       for( i = 0; i < l; ++i ){\r
-                               html[ html.length ] = children[ i ]._create( true );\r
-                       };      \r
-               };\r
-               this._rawNode.innerHTML = html.join( '' );\r
-               return this;\r
-       };\r
+       if( this._destroyed ) return;\r
        \r
-       Node.prototype._ie4afterUpdate = function(){\r
-               var children = this._xnodes,\r
-                       i, l;\r
-               if( !this._ie4dirtyChildren ){\r
-                       if( children && ( l = children.length ) ){\r
-                               for( i = 0; i < l; ++i ){\r
-                                       children[ i ]._ie4afterUpdate();\r
-                               };                              \r
-                       };\r
-                       return this;\r
-               };\r
-               if( children && ( l = children.length ) ){\r
-                       for( i = 0; i < l; ++i ){\r
-                               children[ i ]._afterCreate( this );\r
-                       };      \r
+       if( xnodes && ( i = xnodes.length ) ){\r
+               for( ; i; ){\r
+                       xnodes[ --i ].destroy( true );\r
                };\r
-               delete this._ie4dirtyChildren;\r
+               xnodes.length = 0;\r
        };\r
+       this.unlisten(); // イベントの退避\r
+\r
+       delete Node._chashe[ this._uid ];\r
        \r
-       Node.prototype._ie4containsDirty = function(){\r
-               var children, i;\r
-               if( this._xnodeType !== 1 ) return;\r
-               if( this._ie4dirtyChildren || this._ie4dirty ) return true;\r
-               if( !( children = this._xnodes ) || !( i = children.length ) ) return;\r
-               for( ; i; ){\r
-                       if( children[ --i ]._ie4containsDirty() ) return true;\r
-               };\r
+       if( this._rawNode && this._rawNode.parentNode && this._rawNode.parentNode.tagName ){\r
+               this.remove();\r
+               this._state = Node.STATE_DESTROYED;\r
+               this._destroyed = true; // state                \r
+       } else {\r
+               this.parent._xnodes.splice( this.parent._xnodes.indexOf( this ), 1 );\r
+               !isChild && this._actualRemove();\r
+               this.kill();\r
        };\r
 };\r
 \r
+\r
+\r
 /* --------------------------------------\r
  *  contains\r
  */\r
 Node.prototype.contains = function( v ){\r
-       var node, children, i;\r
+       var node, xnodes, i;\r
        if( !v || !this.parent || this._xnodeType !== -1 ) return false;\r
        // contains ie4+\r
        if( document.contains ){\r
@@ -905,11 +538,11 @@ Node.prototype.contains = function( v ){
        //if( document.compareDocumentPosition ){\r
        //      \r
        //};\r
-       children = this._xnodes;\r
-       if( children.indexOf( v ) !== -1 ) return true;\r
+       xnodes = this._xnodes;\r
+       if( xnodes.indexOf( v ) !== -1 ) return true;\r
        if( ( node = this._rawNode ) && node === v.parentNode ) return false;\r
-       for( i = children.length; i; ){\r
-               if( children[ --i ].contains( v ) ) return true;\r
+       for( i = xnodes.length; i; ){\r
+               if( xnodes[ --i ].contains( v ) ) return true;\r
        };\r
        return false;\r
 };\r
@@ -918,15 +551,9 @@ Node.prototype.contains = function( v ){
  *  getChild\r
  */\r
 Node.prototype.getChildAt = function( index ){\r
-       var children = this._xnodes,\r
-               elm, childNodes, child, xnode;\r
-       if( this._xnodeType !== 1 || index < 0 ) return;\r
-       if( children.length <= index ) return;\r
-       child = children[ index ];\r
-       if( child.constructor === Node ) return child;\r
-       xnode = new Node( child );\r
-       xnode.parent = this;\r
-       return children[ index ] = xnode;\r
+       var xnodes = this._xnodes;\r
+       if( this._xnodeType !== 1 || index < 0 || !xnodes || xnodes.length <= index ) return; //?\r
+       return xnodes[ index ];\r
 };\r
 \r
 \r
@@ -935,18 +562,18 @@ Node.prototype.getChildAt = function( index ){
  */\r
 \r
 Node.prototype.prevNode = function(){\r
-       var parent = this.parent, children, index;\r
+       var parent = this.parent, xnodes, index;\r
        if( !parent ) return;\r
-       children = parent._xnodes;\r
-       index = children.indexOf( this );\r
-       if( 0 < index ) return children[ index - 1 ];\r
+       xnodes = parent._xnodes;\r
+       index = xnodes.indexOf( this );\r
+       if( 0 < index ) return xnodes[ index - 1 ];\r
 };\r
 Node.prototype.nextNode = function(){\r
-       var parent = this.parent, children, index;\r
+       var parent = this.parent, xnodes, index;\r
        if( !parent ) return;\r
-       children = parent._xnodes;\r
-       index    = children.indexOf( this );\r
-       if( index !== -1 && index + 1 < children.length ) return children[ index + 1 ];\r
+       xnodes = parent._xnodes;\r
+       index  = xnodes.indexOf( this );\r
+       if( index + 1 < xnodes.length ) return xnodes[ index + 1 ];\r
 };\r
 Node.prototype.firstChild = function(){\r
        return this.getChildAt( 0 );\r
@@ -970,38 +597,65 @@ Node.prototype.getOrder = function(){
 Node.prototype.className = function( v ){\r
        var node;\r
        // getter\r
-       if(  typeof v !== 'string' ) return this._className;\r
+       if( v === undefined ) return this._className;\r
        // setter\r
        if( this._className === v ) return this;\r
-       if( !v ) delete this._className;\r
-       node = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
-       if( node ) node.className = v;\r
-       this._className = v;\r
-       this._classText = ' class="' + v + '" ';\r
+       if( !v || typeof v !== 'string' ){\r
+               delete this._className;\r
+       } else {\r
+               this._className = v;    \r
+       };\r
+       this._dirty |= X.Dom.Dirty.CLASSNAME;\r
        return this;\r
 };\r
-Node.prototype.addClass = function(){\r
-       \r
+Node.prototype.addClass = function( v ){\r
+       var names = v.split( ' ' ),\r
+               i     = names.length,\r
+               name;\r
+       v = '';\r
+       for( ; i; ){\r
+               name = names[ --i ];\r
+               if( !name ) continue;\r
+               !this.hasClass( name ) && ( v += ( v ? ' ' : '' ) + name );\r
+       };\r
+       return v ? his.className( this._className + ( this._className ? ' ' : '' ) + v ) : this;\r
 };\r
-Node.prototype.removeClass = function(){\r
-       \r
+Node.prototype.removeClass = function( v ){\r
+       var _          = ' ',\r
+               className  = this._className,\r
+               names      = v.split( ' ' ),\r
+               classNames, i, f;\r
+       if( !className ) return this;\r
+       for( classNames = className.split( _ ), i = classNames.length; i; ){\r
+               className = classNames[ --i ];\r
+               for( j = names.length; j; ){\r
+                       if( className === names[ --j ] ){\r
+                               classNames.splice( i, 1 );\r
+                               names.splice( j, 1 );\r
+                               f = true;\r
+                               break;\r
+                       };\r
+               };\r
+       };\r
+       return f ? this.className( classNames.join( ' ' ) ) : this;\r
 };\r
-Node.prototype.toggleClass = function(){\r
-       \r
+Node.prototype.toggleClass = function( v ){\r
+\r
 };\r
-Node.prototype.hasClass = function( className ){\r
+Node.prototype.hasClass = function( v ){\r
        var _ = ' ',\r
-               _className = this._className, i, name;\r
-       if( _className === className ) return true;\r
-       if( !_className ) return false;\r
+               className = this._className,\r
+               i, name;\r
+       if( className === v ) return true;\r
+       if( !className ) return false;\r
        \r
-       _className = _ + _className + _;\r
-       if( _className.indexOf( _ + className + _ ) !== -1 ) return true; // lucky hit\r
+       className = _ + className + _;\r
+       if( className.indexOf( _ + v + _ ) !== -1 ) return true; // lucky hit\r
        \r
-       for( className = className.split( _ ), i = className.length; i; ){\r
-               name = className[ --i ];\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( className.indexOf( _ + name + _ ) === -1 ) return false;\r
        };\r
        return true;\r
 };\r
@@ -1009,25 +663,58 @@ Node.prototype.hasClass = function( className ){
 /* --------------------------------------\r
  *  html, text\r
  */\r
-Node.prototype.html = function( html ){\r
+Node.prototype.html = function( html, opt_wrap ){\r
+       var xnodes, n, i, l;\r
+       // setter\r
        if( html ){\r
                if( this._xnodeType === 3 ){\r
-                       this._text = html;\r
-                       if( this._rawNode ) this._rawNode.data = html;\r
+                       if( this._text !== html ){\r
+                               this._text = html;\r
+                               this.parent && this._reserveUpdate();\r
+                               this._dirty |= X.Dom.Dirty.CONTENT;\r
+                       };\r
                        return this;\r
                };\r
-               return this.empty().append.call( this, X.Dom.parse( html, true ) );\r
+               return this.empty().append.apply( this, X.Dom.parse( html, true ) );\r
+       };\r
+       // getter\r
+       if( this._xnodeType === 3 ){\r
+               return this._text;\r
        };\r
-       // if dirty\r
-       return this._rawNode ? this._rawNode.innerHTML : '';\r
+       \r
+       if( this._dirty & X.Dom.Dirty.CSS && !( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
+               delete this._cssText;\r
+       };\r
+       html = !opt_wrap ? [] : [\r
+               '<', this._tag,\r
+               this._id ? ' id=' + this._id : '',\r
+               this._className ? ' class="' + this._className + '"' : '',\r
+               this._attrText || ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ),\r
+               this._cssText ? ' style="' + this._cssText + '"' : '',\r
+       '>' ];\r
+       \r
+       n = html.length;\r
+       if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
+               for( i = 0; i < l; ++i ){\r
+                       html[ n ] = xnodes[ i ].html( undefined, true );\r
+                       ++n;\r
+               };\r
+       };\r
+       !opt_wrap || X.Dom.DTD.EMPTY[ this._tag.toLowerCase() ] || ( html[ n ] = '<\/' + this._tag + '>' );\r
+\r
+       return html.join( '' );\r
 };\r
 \r
 Node.prototype.text = function( text ){\r
+       var xnodes, n, i;\r
        // setter\r
        if( text ){\r
                if( this._xnodeType === 3 ){\r
-                       this._text = text;\r
-                       if( this._rawNode ) this._rawNode.data = text;\r
+                       if( this._text !== text ){\r
+                               this._text = text;\r
+                               this.parent && this._reserveUpdate();\r
+                               this._dirty |= X.Dom.Dirty.CONTENT;\r
+                       };\r
                        return this;\r
                };\r
                this.empty().createText( text );\r
@@ -1035,11 +722,355 @@ Node.prototype.text = function( text ){
        };\r
        // getter\r
        if( this._xnodeType === 1 ){\r
-               //\r
+               if( ( xnodes = this._xnodes ) && ( i = xnodes.length ) ){\r
+                       for( text = [], n = -1; i; ){\r
+                               text[ ++n ] = xnodes[ --i ].text();\r
+                       };\r
+                       return text.join( '' );\r
+               };\r
+               return '';\r
        };\r
        return this._text;\r
 };\r
 \r
+/* --------------------------------------\r
+ *  Async commit update\r
+ * \r
+ * state:\r
+ *  0 : no_rawnode\r
+ *  1 : not_added\r
+ *  3 : dirty\r
+ *  4 : clean\r
+ * \r
+ * remove :\r
+ * root._reserveRemoval = [] に追加。commitUpdate で remove して state は not_added\r
+ * add :\r
+ * root._reserveRemoval にいたら消す, new_parent._xnodes に挿入 steta は not_added にして commitUpdate を待つ\r
+ */\r
+       \r
+Node.prototype._reserveUpdate = function( child ){\r
+       var root = Node.root;\r
+       //if( !root ) return;\r
+       //child && ( child._dirty = true );\r
+       if( root && !root._updateReserved ) root._updateReserved = X.Timer.requestFrame( root, root._startUpdate );\r
+};\r
+\r
+Node.prototype._startUpdate = function(){\r
+       var removal, i, xnode, tmp;\r
+       \r
+       if( this._updateReserved ){\r
+               //X.Timer.cancelFrame( this._updateReserved );\r
+               delete this._updateReserved;\r
+       } else {\r
+               return;\r
+       };\r
+\r
+       removal = Node._reserveRemoval;\r
+       i       = removal.length;\r
+       \r
+       tmp = this._rawNode.style.visibility;\r
+       //this._rawNode.style.visibility = 'hidden';\r
+       \r
+       for( ; i; ){\r
+               xnode = removal[ --i ];\r
+               xnode._actualRemove();\r
+               xnode._destroyed && xnode.kill();\r
+       };\r
+       this._commitUpdate();\r
+       \r
+       //this._rawNode.style.visibility = tmp;\r
+};\r
+\r
+Node.prototype._commitUpdate =\r
+       document.getElementById ?\r
+               ( function( parentElement, nextElement ){\r
+                       var elm = this._rawNode,\r
+                               xnodes, l, i, next, k, v;\r
+\r
+                       if( !elm ){\r
+                               nextElement ?\r
+                                       parentElement.insertBefore( this._actualCreate(), nextElement ) :\r
+                                       parentElement.appendChild( this._actualCreate() );\r
+                               this._afterActualCreate();\r
+                               return this._rawNode;\r
+                       } else          \r
+                       if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
+                               for( ; l; ){\r
+                                       next = xnodes[ --l ]._commitUpdate( elm, next );\r
+                               };\r
+                       };\r
+\r
+                       // textNode\r
+                       if( this._dirty & X.Dom.Dirty.CONTENT ) elm.data = X.Dom.chrReferanceTo( this._text );\r
+                       // className\r
+                       if( this._dirty & X.Dom.Dirty.CLASSNAME ) elm.className = this._className;\r
+                       // style\r
+                       if( this._dirty & X.Dom.Dirty.CSS ){\r
+                               if( this._cssText || ( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
+                                       elm.style.cssText = this._cssText;\r
+                               } else {\r
+                                       elm.removeAttribute( 'style' );\r
+                                       delete this._cssText;\r
+                               };\r
+                       };\r
+                       // attr\r
+                       if( this._newAttrs ){\r
+                               for( k in this._newAttrs ){\r
+                                       ( v = this._newAttrs[ k ] ) === undefined ?\r
+                                               elm.removeAttribute( k ) :\r
+                                               ( elm[ k ] = v );\r
+                               };\r
+                               delete this._newAttrs;\r
+                       };\r
+                       \r
+                       delete this._dirty;\r
+                       \r
+                       return elm;\r
+               }) :\r
+       document.all ? \r
+               ( function( parentElement, prevElement ){\r
+                       var elm    = this._rawNode || this._ie4getRawNode(),\r
+                               xnodes = this._xnodes,\r
+                               l      = xnodes && xnodes.length,\r
+                               i, html, elm, child, prev, k, v;\r
+\r
+                       if( !elm ){\r
+                               prevElement ?\r
+                                       prevElement.insertAdjacentText( 'AfterEnd', this._actualCreate() ) :\r
+                                       parentElement.insertAdjacentText( 'BeforeEnd', this._actualCreate() );\r
+                               this._afterActualCreate();\r
+                               return this._rawNode || this._ie4getRawNode();\r
+                       } else\r
+                       if( this._dirty | X.Dom.Dirty.IE4_TEXTNODE_FIX ){\r
+                               html = [];\r
+                               for( i = 0; i < l; ++i ){\r
+                                       html[ i ] = xnodes[ i ]._actualCreate();\r
+                               };\r
+                               elm.innerHTML = html.join( '' );\r
+                               for( i = 0; i < l; ++i ){\r
+                                       xnodes[ i ]._afterActualCreate();\r
+                               };\r
+                       } else                  \r
+                       if( l ){\r
+                               for( i = 0; i < l; ++i ){\r
+                                       prev = xnodes[ i ]._commitUpdate( elm, prev );\r
+                               };\r
+                       };\r
+\r
+                       // fake textNode\r
+                       if( this._dirty & X.Dom.Dirty.CONTENT ) elm.innerHTML = this._text;\r
+                       // className\r
+                       if( this._dirty & X.Dom.Dirty.CLASSNAME ) elm.className = this._className;\r
+                       // style\r
+                       if( this._dirty & X.Dom.Dirty.CSS ){\r
+                               if( this._cssText || ( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
+                                       elm.style.cssText = this._cssText;\r
+                               } else {\r
+                                       elm.removeAttribute( 'style' );\r
+                                       delete this._cssText;\r
+                               };\r
+                       };\r
+                       // attr\r
+                       if( this._newAttrs ){\r
+                               for( k in this._newAttrs ){\r
+                                       ( v = this._newAttrs[ k ] ) === undefined ?\r
+                                               elm.removeAttribute( k ) :\r
+                                               elm.setAttribute( k, v );\r
+                               };\r
+                               delete this._newAttrs;\r
+                       };\r
+                       \r
+                       delete this._dirty;\r
+                       \r
+                       return elm;\r
+               }) :\r
+               (function(){});\r
+\r
+/* --------------------------------------\r
+ *  Create\r
+ * \r
+ * http://d.hatena.ne.jp/uupaa/20080718/1216362040\r
+ * DOM Rangeが使える環境(Firefox2+,Opera9+,Safari3+)なら、innerHTMLいらずで、ガーって書けます。\r
+ * return document.createRange().createContextualFragment("<div><select><option></option></select></div>");\r
+ * insertAdjacentHTML\r
+ * \r
+ * ie7 以下では iframe の frameborder や、input name は、createElement 後に aetAttribute しても無視される\r
+ * \r
+ * fragument がある場合 children も足して\r
+ * Mozilla: 1.0+, IE: 6.0+, Netscape: 2.0+, Safari: 1.0+, Opera: 7.0+\r
+ * ie6 大丈夫?fragment の場合リークしないか?チェックが必要\r
+ * http://msdn.microsoft.com/ja-jp/library/bb250448%28v=vs.85%29.aspx\r
+ * \r
+ * document.createElement of ie4 is only for OPTION & IMAGE.\r
+ */\r
+Node.prototype._actualCreate =\r
+       document.getElementById ? (function( isChild ){\r
+               var elm = this._rawNode,\r
+                       xnodes, frg, i, l;\r
+               \r
+               if( this._xnodeType === 3 ){\r
+                       return elm || ( this._rawNode = document.createTextNode( X.Dom.chrReferanceTo( this._text ) ) );\r
+               };\r
+               \r
+               if( !elm ){\r
+                       if( this._dirty & X.Dom.Dirty.CSS && !( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
+                               delete this._cssText;\r
+                       };\r
+                       this._isNew = true;\r
+                       this._rawNode = elm =\r
+                               X.UA.IE ?\r
+                                       document.createElement( [\r
+                                               '<', this._tag,\r
+                                                       ' UID="', this._uid, '"',\r
+                                                       this._id ? ' id="' + this._id + '"' : '',\r
+                                                       this._className ? ' class="' + this._className + '"' : '',\r
+                                                       this._attrText || ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ),\r
+                                                       this._cssText ? ' style="' + this._cssText + '"' : '',\r
+                                               '>' ].join( '' ) ):\r
+                                       document.createElement( this._tag );\r
+               };\r
+               if( Node._useDocumentFragment ){\r
+                       if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
+                               !isChild && ( frg = Node._useDocumentFragment ).appendChild( elm );\r
+                               for( i = 0; i < l; ++i ){\r
+                                       elm.appendChild( xnodes[ i ]._actualCreate( true ) );\r
+                               };\r
+                               return frg || elm;\r
+                       };\r
+               };\r
+               \r
+               return elm;\r
+       }) :\r
+       document.all ? (function(){\r
+               var uid = this._uid,\r
+                       html, xnodes, n, i, l;\r
+               \r
+               if( this._xnodeType === 3 ){\r
+                       html = [ '<font id=ie4uid', uid, ' UID=', uid, '>', this._text, '</font>' ];// fake textNode\r
+               } else {\r
+                       if( this._dirty & X.Dom.Dirty.CSS && !( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
+                               delete this._cssText;\r
+                       };\r
+                       html = [\r
+                               '<', this._tag, ' id=', ( this._id || ( 'ie4uid' + uid ) ), ' UID=', uid,\r
+                               this._className ? ' class="' + this._className + '"' : '',\r
+                               this._attrText || ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ),\r
+                               this._cssText ? ' style="' + this._cssText + '"' : '',\r
+                       '>' ];\r
+                       \r
+                       n = html.length;\r
+                       if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
+                               for( i = 0; i < l; ++i ){\r
+                                       html[ n ] = xnodes[ i ]._actualCreate();\r
+                                       ++n;\r
+                               };\r
+                       };\r
+                       X.Dom.DTD.EMPTY[ this._tag.toLowerCase() ] || ( html[ n ] = '<\/' + this._tag + '>' );\r
+                       \r
+                       delete this._newAttrs;\r
+               };\r
+               delete this._dirty;\r
+               delete this._rawNode;\r
+               \r
+               return html.join( '' );\r
+       }) :\r
+       (function(){});\r
+\r
+Node.prototype._afterActualCreate =\r
+       document.getElementById ? (function(){\r
+               var xnodes, l, elm, attrs, k, i;\r
+               \r
+               this.state  = Node.STATE_STAGED;\r
+               delete this._dirty;\r
+               if( this._xnodeType === 3 ){\r
+                       //elm.UID = this._uid;\r
+                       return this;\r
+               };\r
+               delete this._newAttrs;\r
+                       \r
+               xnodes = this._xnodes;\r
+               l      = xnodes && xnodes.length;\r
+               elm    = this._rawNode;\r
+               \r
+               if( this._isNew ){\r
+                       if( !Node._useDocumentFragment && l ){// docFrg が使えない場合、doc 追加後に子を追加\r
+                               for( i = 0; i < l; ++i ){\r
+                                       elm.appendChild( xnodes[ i ]._actualCreate( true ) );\r
+                               };\r
+                       };\r
+                       if( !X.UA.IE ){\r
+                               elm.UID = this._uid;\r
+                               if( this._id ) elm.id = this._id;\r
+                               if( this._className ) elm.className = this._className;\r
+                               if( attrs = this._attrs ){\r
+                                       for( k in attrs ){\r
+                                               elm[ k ] = attrs[ k ];\r
+                                       };\r
+                               };\r
+                               elm.style.cssText = this._cssText;\r
+                       };\r
+                       this._restoreEvent();// イベントの復帰\r
+                       delete this._isNew;\r
+               };\r
+               if( l ){\r
+                       for( i = 0; i < l; ++i ){\r
+                               xnodes[ i ]._afterActualCreate();\r
+                       };\r
+               };\r
+               return this;\r
+       }) :\r
+       document.all ? (function(){\r
+               var xnodes, i;\r
+               this.state = Node.STATE_STAGED;\r
+               \r
+               if( this._xnodeType !== 1 ) return this;\r
+               \r
+               if( ( xnodes = this._xnodes ) && ( i = xnodes.length ) ){\r
+                       for( ; i; ){\r
+                               xnodes[ --i ]._afterActualCreate();\r
+                       };\r
+               };\r
+               return this._restoreEvent();// イベントの復帰\r
+       }) :\r
+       (function(){});\r
+       \r
+Node.prototype._actualRemove =\r
+       document.getElementById ?\r
+               ( function( isChild ){\r
+                       var xnodes = this._xnodes,\r
+                               elm    = this._rawNode,\r
+                               child, i, l;\r
+                       if( xnodes && ( l = xnodes.length ) ){\r
+                               for( i = 0; i < l; ++i ){\r
+                                       child = xnodes[ i ];\r
+                                       child._xnodeType === 1 && child._actualRemove( true );\r
+                               };\r
+                       };\r
+                       if( !elm ) return;\r
+                       this._xnodeType === 1 && this._migrateEvent();// イベントの退避\r
+                       // elm.parentNode.tagName check tagName is for ie7\r
+                       !isChild && elm.parentNode && elm.parentNode.tagName && elm.parentNode.removeChild( elm );\r
+               }) :\r
+       document.all ? \r
+               ( function( isChild ){\r
+                       var xnodes = this._xnodes,\r
+                               elm    = this._rawNode || this._ie4getRawNode(),\r
+                               i, l, xnode;\r
+                       if( xnodes && ( l = xnodes.length ) ){\r
+                               for( i = 0; i < l; ++i ){\r
+                                       xnodes[ i ]._actualRemove( true );\r
+                               };\r
+                       };\r
+                       if( !elm ) return;\r
+                       this._xnodeType === 1 && this._migrateEvent();// イベントの退避\r
+                       delete this._rawNode;\r
+                       elm.removeAttribute( 'id', '' );\r
+                       document.all[ 'ie4uid' + this._uid ] = null;\r
+                       if( !isChild ) elm.outerHTML = '';\r
+               }) :\r
+               (function(){});\r
+       \r
+       \r
 //})( window, document );\r
 \r
 \r
index c601263..37ab83f 100644 (file)
@@ -6,15 +6,15 @@
  */
 
 if( window.addEventListener ){
-       X.Dom.Event = function( e ){
+       X.Dom.Event = function( e, xnode ){
                //this._event        = e;
                this.type          = e.type;
                
                //http://www.quirksmode.org/js/events_properties.html
-               this.target        = e.target.nodeType === 3 ? e.target.parentNode : e.target;// defeat Safari bug // xnode
+               this.target        = Node._getXNode( e.target.nodeType === 3 ? e.target.parentNode : e.target );// defeat Safari bug // xnode
                
-               this.currentTarget = e.currentTarget; // xnode
-               this.relatedTarget = e.relatedTarget; // xnode
+               this.currentTarget = xnode; // xnode
+               this.relatedTarget = Node._getXNode( e.relatedTarget ); // xnode
                this.eventPhase    = e.eventPhase;
                
                this.clientX       = e.clientX;
@@ -53,12 +53,7 @@ if( window.addEventListener ){
                        this.touches        = e.touches;
                        this.changedTouches = e.changedTouches;
                        this.targetTouches  = e.targetTouches;
-                       //this.altKey         = e.altKey;
-                       //this.ctrlKey        = e.ctrlKey;
                        this.metaKey        = e.metaKey;
-                       //this.shiftKey       = e.shiftKey;
-                       //this.type           = e.type;
-                       //this.target         = e.target;
                } else
                if( e.constructor === window.PointerEvent ){
                        // PointerEvent;
@@ -77,14 +72,14 @@ if( window.addEventListener ){
                };
        };
 } else {
-       X.Dom.Event = function( e, element ){
+       X.Dom.Event = function( e, xnode, element ){
                var btn;
                
                //this._event        = e;
                this.type          = e.type;
-               this.target        = e.srcElement; // xnode
-               this.currentTarget = element; // xnode
-               this.relatedTarget = e.formElement ? e.formElement : e.toElement; // xnode
+               this.target        = Node._getXNode( e.srcElement ); // xnode
+               this.currentTarget = xnode; // xnode
+               this.relatedTarget = Node._getXNode( e.formElement ? e.formElement : e.toElement ); // xnode
                this.eventPhase    = e.srcElement === element ? 2: 3;
                
                this.clientX       = e.clientX;
@@ -228,7 +223,7 @@ X.Dom.Node.prototype._removeEvent =
 X.Dom.Node.prototype.handleEvent =
        document.removeEventListener ?
                (function( e ){
-                       var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( e ) );
+                       var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( e, this ) );
 
                        if( ret & X.Callback.STOP_PROPAGATION ){
                                e.stopPropagation();
@@ -239,7 +234,7 @@ X.Dom.Node.prototype.handleEvent =
                        };
                }) :
                (function(){
-                       var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( event, this._rawNode ) );
+                       var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( event, this, this._rawNode ) );
 
                        if( ret & X.Callback.STOP_PROPAGATION ){
                                event.cancelBubble = true;
@@ -309,120 +304,227 @@ X.Dom.listenOnce( X.Dom.Event.VIEW_RESIZED, function(e){ console.log( 'X.Dom VIE
  */
 X.Dom.listenOnce( X.Dom.Event.DOM_INIT, function(){
        
-       Node._html = document.documentElement ? new Node( document.documentElement ) : null;
-       //alert( document.all.tags('html')[ 0 ].tagName );
+       Node._html = document.documentElement ?
+                       new Node( document.documentElement ) :
+               document.getElementsByTagName ?
+                       new Node( document.getElementsByTagName( 'html' )[ 0 ] ) :
+               document.all ?
+                       new Node( document.all.tags( 'html' )[ 0 ] ) :
+                       null;
+
        var r    = Node.root = new Node( document.body ),
                body = r._rawNode,
-               createTree, n = 0, s;
+               createTree, n = 0, xnodes, s;
        r.appendTo = r.appendToRoot = r.before = r.after = r.clone = r.remove = r.destroy = r.prevNode = r.nextNode = new Function( 'return this' );
        
-       if( body.childNodes ){
-               /*
-                * body.innerHTML(可能なら outerHTML を使って属性を控える)
-                */
-               createTree = function( xnode, elm, skipCleanup ){
-                       var     children = elm.childNodes,
-                               i = 0,
-                               l = children.length,
-                               child, _xnode, text;
-                       for( ; i < children.length; ){
-                               child = children[ i ];
-                               switch( child.nodeType ){
-                                       case 1 :
-                                               if( !xnode._xnodes ) xnode._xnodes = [];
-                                               xnode._xnodes[ xnode._xnodes.length ] = _xnode = new Node( child );
-                                               // attr の取得
+       createTree =
+               body.childNodes ?
+                       (function( xnode, childNodes, skipCleanup ){
+                               var i = 0,
+                                       l,
+                                       j = 0,
+                                       child, _xnode, f, tag, text, _xtext, ary = [];
+                               //Array.prototype.push.apply( ary, childNodes );
+                               ary = X.copyArray( childNodes );
+                               childNodes = ary;
+                               l = childNodes.length;
+                               //xnode._dirtychildNodes = true;
+                               for( ; i < l; ++i ){
+                                       child = childNodes[ i ];
+                                       if( ( child.nodeType !== 1 && child.nodeType !== 3 ) || child.tagName === '!' ){
+                                               child.parentNode.removeChild( child );
+                                               continue;
+                                       };
+                                       //if( child.tagName === '!' ) continue;
+                                       f = false;
+                                       while( xnode._xnodes && j < xnode._xnodes.length ){
+                                               _xnode = xnode._xnodes[ j ];
                                                _xnode.parent = xnode;
-                                               child.childNodes.length && createTree( _xnode, child, skipCleanup || 0 <= X.Dom.skipCleanupTagNames.indexOf( child.tagName ) );//.toLowerCase() ) );
-                                               break;
-                                       case 3 :
-                                               if( skipCleanup || ( ( text = child.data ) && ( text = X.Dom.cleanupWhiteSpace( text ) ) !== ' ' ) ){
-                                                       if( !skipCleanup ) child.data = text;
-                                                       if( !xnode._xnodes ) xnode._xnodes = [];
-                                                       xnode._xnodes[ xnode._xnodes.length ] = _xnode = new Node( child );
-                                                       _xnode.parent = xnode;
-                                                       break;                                                  
-                                               };
-                                       default :
-                                               elm.removeChild( child );
-                                               ++n;
-                                               continue;                                                               
-                               };
-                               ++i;
-                       };
-               };
-               createTree( r, body );
-       } else
-       if( body.children ){
-               createTree = function( xnode, children, skipCleanup ){
-                       var i = 0,
-                               l = children.length,
-                               j = 0,
-                               child, _xnode, f, tag, text;
 
-                       xnode._ie4dirtyChildren = true;
-                       for( ; i < l; ++i ){
-                               child = children[ i ];
-                               if( child.tagName === '!' ) continue;
-                               f = false;
-                               while( j < xnode._xnodes.length ){
-                                       _xnode = xnode._xnodes[ j ];
-                                       _xnode.parent    = xnode;
-                                       _xnode._ie4dirty = true;
-                                       if( _xnode._xnodeType === 1 ){
-                                               tag = child.tagName; //.toLowerCase();
-                                               if( _xnode._tag !== tag ){
-                                                       alert( _xnode._tag + ' !== ' + child.tagName + ' * ' + child.outerHTML );
-                                               } else {
+                                               if( _xnode._xnodeType === 1 ){
+                                                       _xtext = null;
+                                                       if( child.nodeType !== 1 ){
+                                                               if( !( text = child.data ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' || !text ){
+                                                                       child.parentNode.removeChild( child );
+                                                                       break;
+                                                               };
+                                                               alert( '[' +xnode._tag + '>' +_xnode._tag + '] !== ' + child.nodeType + '\n' + child.data );
+                                                               ++j;
+                                                               continue;
+                                                       };
+                                                       tag = child.tagName;
+                                                       if( _xnode._tag.toUpperCase() !== tag ){
+                                                               alert( '[' +xnode._tag + '>' +_xnode._tag + ' ' + (_xnode._xnodes ? _xnode._xnodes.length : '' ) + '] !== ' + child.tagName + ' ' + (child.childNodes ? child.childNodes.length : '' ) + '\n' + child.outerHTML );
+                                                               ++j;
+                                                               continue;
+                                                       } else {
+                                                               _xnode._rawNode = child;
+                                                               child.UID = _xnode._uid;
+                                                               if( 0 <= X.Dom.cleanupTagNames.indexOf( tag.toLowerCase() ) ){
+                                                                       //alert( '[' +xnode._tag + '>' + _xnode._tag + '] remove ... ' );
+                                                                       _xnode.destroy();
+                                                                       ++n;
+                                                                       continue;
+                                                               } else {
+                                                                       //alert( '[' +xnode._tag + '>' + _xnode._tag + ' ' + (_xnode._xnodes ? _xnode._xnodes.length : '' ) + '] === ' + child.tagName + ' ' + (child.childNodes ? child.childNodes.length : '' ) + ' Hit\n' + child.outerHTML );
+                                                                       child.childNodes.length && createTree( _xnode, child.childNodes, skipCleanup || 0 <= X.Dom.skipCleanupTagNames.indexOf( tag.toLowerCase() ) );
+                                                               };
+                                                               f = true;
+                                                               ++j;
+                                                               break;
+                                                       };
+                                               } else
+                                               if( _xnode._xnodeType === 3 ){
+                                                       if( child.nodeType !== 3 ){
+                                                               if( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
+                                                                       console.log( '[' +xnode._tag + '>' + _xnode._uid + '] destroy ... ' );
+                                                                       _xnode.destroy();
+                                                                       ++n;
+                                                                       continue;
+                                                               };
+                                                               alert(  xnode._tag + '>' + '"' + _xnode._text + '" !== ' + child.tagName + '\n' + child.outerHTML );
+                                                               ++j;
+                                                               continue;
+                                                       };
+                                                       
                                                        _xnode._rawNode = child;
-                                                       //!( _xnode._id = child.getAttribute( 'id' ) ) && child.setAttribute( 'id', ( _xnode._ie4uid = 'ie4uid' + _xnode._uid ) );
-                                                       !_xnode._id && child.setAttribute( 'id', ( _xnode._ie4uid = 'ie4uid' + _xnode._uid ) );
-                                                       child.setAttribute( 'UID', '' + _xnode._uid );
-                                                       child.children.length && createTree( _xnode, child.children, skipCleanup || 0 <= X.Dom.skipCleanupTagNames.indexOf( tag ) );
-                                                       f = true;
+                                                       
+                                                       if( !skipCleanup ){
+                                                               if( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
+                                                                       console.log( '[' +xnode._tag + '>' + _xnode._uid + '] destroy ... ' );
+                                                                       _xnode.destroy();
+                                                                       ++n;
+                                                                       continue;
+                                                               };
+                                                               if( _xtext ){
+                                                                       _xtext.text( _xtext._text + text );
+                                                                       console.log( '[' +xnode._tag + '>' + _xnode._uid + '] xtext,destroy ... ' );
+                                                                       _xnode.destroy();
+                                                                       ++n;
+                                                                       continue;
+                                                               } else {
+                                                                       //alert( xnode._tag + '>' + '"' + text + '"\n' + child.data );
+                                                                       _xnode.text( text );
+                                                               };
+                                                       } else
+                                                       if( _xtext ){
+                                                               _xtext.text( _xtext._text + _xnode.text );
+                                                               console.log( '[' +xnode._tag + '>' + _xnode._uid + '] xtext,destroy ... ' );
+                                                               _xnode.destroy();
+                                                               ++n;
+                                                               continue;
+                                                       };
+                                                       _xtext = _xtext || _xnode;
                                                        ++j;
                                                        break;
+                                               } else {
+                                                       alert( 'no hit!' )
                                                };
-                                       } else
+                                               ++j;
+
+                                       };                              
+                                       //if( !f ) alert( '**** ' + child.outerHTML );
+                               };
+                               while( xnode._xnodes && j < xnode._xnodes.length ){
+                                       _xnode = xnode._xnodes[ j ];
+                                       _xnode.parent = xnode;
                                        if( _xnode._xnodeType === 3 ){
-                                               if( !skipCleanup && ( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ) ){
-                                                       _xnode.remove();
+                                               if( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
+                                                       console.log( '[' +xnode._tag + '>' + _xnode._uid + '] destroy ... ' );
+                                                       _xnode.destroy();
                                                        ++n;
                                                        continue;
                                                };
-                                               if( !skipCleanup ) _xnode._text = text;
                                        };
                                        ++j;
                                };
-                               if( !f ) alert( '**** ' + child.outerHTML );
-                       };
-               };
-               
-               r._xnodes = [];
-               Node.skipCreate = true;
-               /*
-                * http://support.microsoft.com/kb/812417/ja
-                * PRB: outerHTML の HTML 要素のプロパティは、既定の属性は表示されません。
-                * 
-                * body.innerHTML でなく、 body.outerHTML
-                */
-               r._xnodes.push.apply( r._xnodes, X.Dom.parse( body.innerHTML, true ) );
-               delete Node.skipCreate;
-               createTree( r, body.children );
-               //alert(n +  ' ' + body.innerHTML);
-               r._ie4reserveUpdate();
-               //alert(n +  ' ' + body.innerHTML);
-               r._ie4startUpdate();
-               alert(n +  ' ' + body.innerHTML);
-       } else {
-               
-       };
+                       }) :
+               body.children ?
+                       (function( xnode, children, skipCleanup ){
+                               var i = 0,
+                                       l = children.length,
+                                       j = 0,
+                                       flag = 0,
+                                       child, _xnode, tag, text;
+       
+                               xnode._dirtyChildren = true;
+                               for( ; i < l; ++i ){
+                                       child = children[ i ];
+                                       if( child.tagName === '!' ) continue;
+                                       while( j < xnode._xnodes.length ){
+                                               _xnode = xnode._xnodes[ j ];
+                                               _xnode.parent = xnode;
+
+                                               if( _xnode._xnodeType === 1 ){
+                                                       tag = child.tagName;
+                                                       if( _xnode._tag !== tag ){
+                                                               alert( _xnode._tag + ' !== ' + child.tagName + ' * ' + child.outerHTML );
+                                                       } else {
+                                                               _xnode._rawNode = child;
+                                                               !_xnode._id && child.setAttribute( 'id', ( _xnode._ie4uid = 'ie4uid' + _xnode._uid ) );
+                                                               child.setAttribute( 'UID', '' + _xnode._uid );
+                                                               if( 0 <= X.Dom.cleanupTagNames.indexOf( tag.toLowerCase() ) ){
+                                                                       _xnode.destroy();
+                                                                       ++n;
+                                                                       continue;
+                                                               } else {
+                                                                       child.children.length && createTree( _xnode, child.children, skipCleanup || 0 <= X.Dom.skipCleanupTagNames.indexOf( tag.toLowerCase() ) );
+                                                                       tag === 'INPUT' && ( !_xnode._attrs || !_xnode._attrs.type ) && ( _xnode._attrs.type = 'text' );
+                                                               };
+                                                               flag |= 3;
+                                                               ++j;
+                                                               break;
+                                                       };
+                                               } else
+                                               if( _xnode._xnodeType === 3 ){
+                                                       flag |= 4;
+                                                       if( !skipCleanup ){
+                                                               if( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
+                                                                       _xnode.destroy();
+                                                                       ++n;
+                                                                       continue;
+                                                               };
+                                                               _xnode.text( text );
+                                                       };
+                                               };
+                                               ++j;
+                                       };
+                                       if( !( flag & 1 ) ) alert( '**** ' + child.outerHTML );
+                                       flag &= 6;
+                               };
+                               // textNode がある
+                               ( flag & 4 ) && ( xnode._dirty |= X.Dom.Dirty.IE4_TEXTNODE_FIX );                       
+                       }) :
+                       (function(){});
+       
+       r._xnodes = xnodes = [];
+       // body の属性値の取得
+
+       Node.skipCreate = true;
+       /*
+        * http://support.microsoft.com/kb/812417/ja
+        * PRB: outerHTML の HTML 要素のプロパティは、既定の属性は表示されません。
+        * 
+        * body.innerHTML でなく、 body.outerHTML
+        */
+       xnodes.push.apply( xnodes, X.Dom.parse( body.innerHTML, true ) );
+       delete Node.skipCreate;
+       
+       //alert(n +  ' ' + body.innerHTML);
+       
+       createTree( r, body.children );
        
        //r.width  = new Function( 'return X.Dom.getSize()[ 0 ]' );
        //r.height = new Function( 'return X.Dom.getSize()[ 1 ]' );
+       i = xnodes.length;
+       Node._systemNode = s = r.create( 'div' ).className( 'hidden-sysyem-node' );
+       //alert( i + ' -> ' + xnodes.length );
+       
+       r._startUpdate();
+       
+       xnodes.splice( xnodes.indexOf( s ), 1 ); // hide from api user
        
-       Node._systemNode = r.create( 'div' ).className( 'hidden-sysyem-node' );
-       r._xnodes.splice( r._xnodes.indexOf( Node._systemNode ), 1 ); // hide from api user
+       //alert(n +  ' ' + body.innerHTML);
 } );
 
 
index f32f719..172365a 100644 (file)
@@ -10,7 +10,7 @@ X.Dom.BoxModel = {
 
 X.Dom.listenOnce( X.Dom.Event.DOM_INIT, function(){
 
-       var elm = Node._systemNode._rawNode;
+       var elm = Node._systemNode._rawNode || Node._systemNode._ie4getRawNode();
        elm.style.cssText = 'width:10px;padding:1px;border:2px solid #0;margin:4px;';
        
        X.Dom.BoxModel.defaultBoxModel = elm.offsetWidth === 10 ?
@@ -45,7 +45,7 @@ Node.prototype.width = function(){
        } else
        if( document.all ){
                if( !( elm = this._ie4getRawNode() ) ) return 0;
-               Node.root._ie4reserved === true && Node.root._ie4startUpdate();
+               Node.root._updateReserved === true && Node.root._startUpdate();
                return elm.offsetWidth;
        } else {
                
@@ -61,7 +61,7 @@ Node.prototype.height = function(){
        } else
        if( document.all ){
                if( !( elm = this._ie4getRawNode() ) ) return 0;
-               Node.root._ie4reserved === true && Node.root._ie4startUpdate();
+               Node.root._updateReserved === true && Node.root._startUpdate();
                return elm.offsetHeight;                
        } else {
                
@@ -86,7 +86,7 @@ Node.prototype.x = function(){
        } else
        if( document.all ){
                if( !( elm = this._ie4getRawNode() ) ) return 0;
-               Node.root._ie4reserved === true && Node.root._ie4startUpdate();
+               Node.root._updateReserved === true && Node.root._startUpdate();
                return elm.offsetLeft;          
        } else {
                
@@ -103,7 +103,7 @@ Node.prototype.y = function(){
        } else
        if( document.all ){
                if( !( elm = this._ie4getRawNode() ) ) return 0;
-               Node.root._ie4reserved === true && Node.root._ie4startUpdate();
+               Node.root._updateReserved === true && Node.root._startUpdate();
                return elm.offsetTop;           
        } else {
                
index a9566b0..fadd4f9 100644 (file)
@@ -173,9 +173,9 @@ X.Dom.Attr = {
        },\r
        renameForTag : {},\r
        objToAttrText : function( obj ){\r
-               var attrs = [], noValue = X.Dom.Attr.noValue, p;\r
+               var noValue = X.Dom.Attr.noValue, attrs = [], n = -1, p;\r
                for( p in obj ){\r
-                       attrs[ attrs.length ] = noValue[ p ] ? p : [ p, '="', obj[ p ], '"' ].join( '' );\r
+                       attrs[ ++n ] = noValue[ p ] ? p : [ p, '="', obj[ p ], '"' ].join( '' );\r
                };\r
                return attrs.join( ' ' );\r
        }\r
@@ -204,31 +204,31 @@ X.Dom.Attr = {
  * \r
  */\r
 X.Dom.Node.prototype.attr = function( nameOrObj /* v */ ){\r
-       var attrs = this._attrs,\r
-               node, v, name;\r
+       var attrs, newAttrs, v, name;\r
        \r
        if( this._xnodeType !== 1 ) return this;\r
        \r
        if( nameOrObj && X.Type.isObject( nameOrObj ) ){\r
-               if( !attrs ) attrs = this._attrs = {};\r
-               node = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
+               if( !( attrs = this._attrs ) ) attrs = this._attrs = {};\r
+               if( !( newAttrs = this._newAttrs ) ) newAttrs = this._newAttrs = {};\r
+               \r
                for( p in nameOrObj ){\r
-                       this.__attr( node, attrs, p, nameOrObj[ p ] );\r
+                       this.__attr( attrs, newAttrs, p, nameOrObj[ p ] );\r
                };\r
                delete this._attrText; // = X.Dom.Attr.objToAttrText( attrs );\r
-               this._attrUpdated = true;\r
+               this._dirty |= X.Dom.Dirty.ATTR;\r
+               this.parent && this._reserveUpdate();\r
                return this;\r
        } else\r
        if( 1 < arguments.length ){\r
                // setter\r
-               // this._attrText use when Node.create()\r
-               if( !attrs ) attrs = this._attrs = {};\r
-               this.__attr(\r
-                       this._ie4getRawNode ? ( this._rawNode || this._ie4getRawNode() ) : this._rawNode,\r
-                       attrs, nameOrObj, arguments[ 1 ]\r
-               );\r
+               if( !( attrs = this._attrs ) ) attrs = this._attrs = {};\r
+               if( !( newAttrs = this._newAttrs ) ) newAttrs = this._newAttrs = {};\r
+               \r
+               this.__attr( attrs, newAttrs, nameOrObj, arguments[ 1 ] );\r
                delete this._attrText; // = X.Dom.Attr.objToAttrText( attrs );\r
-               this._attrUpdated = true;\r
+               this._dirty |= X.Dom.Dirty.ATTR;\r
+               this.parent && this._reserveUpdate();\r
                return this;\r
        } else\r
        if( typeof nameOrObj === 'string' ){\r
@@ -238,34 +238,28 @@ X.Dom.Node.prototype.attr = function( nameOrObj /* v */ ){
                return attrs[ v ];\r
        };\r
 };\r
-X.Dom.Node.prototype.__attr = function( node, attrs, name, v ){\r
-       name = X.Dom.Attr.renameForTag[ name ] || name;\r
+X.Dom.Node.prototype.__attr = function( attrs, newAttrs, name, v ){\r
+       if( name === 'UID' ) return;\r
+       if( name === 'id' ){\r
+               this._id = v !== 'ie4uid' + this._uid ? v : undefined;\r
+               return;\r
+       };      \r
+       if( name === 'class' ) return this.className( v );      \r
+       if( name === 'style' ) return this.cssText( v );\r
        \r
-       if( attrs[ name ] === v ) return;\r
-       if( name === 'style' ){\r
-               return this.cssText( v );\r
-       };\r
        if( name.indexOf( 'on' ) === 0 ){\r
                X.Notification.warn( 'xnode.attr("' + name + '") is wrong, xnode.listen() & xnode.unlisten().' );\r
                return;\r
        };\r
-       // className\r
-       if( name === 'class' ) return this.className( v );\r
-       // update node\r
-       if( node ){\r
-               this._ie4getRawNode ?\r
-                       v ? node.setAttribute( name, v ) : node.removeAttribute( name ) : // val\r
-                       ( node[ X.Dom.Attr.renameForDOM[ name ] || name ] = v || undefined ); // val\r
-       };\r
-       // id\r
-       if( name === 'id' ){\r
-               this._id = v === 'ie4uid' + this._uid ? undefined : v || undefined;\r
-               return;\r
-       };\r
-       // update this._attrs\r
-       if( !v ){\r
-               delete attrs[ name ];\r
+       \r
+       name = X.Dom.Attr.renameForTag[ name ] || name;\r
+       if( attrs[ name ] === v ) return;\r
+       \r
+       if( v == null ){\r
+               newAttrs[ name ] = undefined;\r
+               if( attrs.hasOwnProperty( name ) ) delete attrs[ name ];\r
        } else {\r
-               attrs[ name ] = v;\r
+               newAttrs[ name ] = attrs[ name ] = v;\r
        };\r
-};
\ No newline at end of file
+};\r
+\r
index 1edbdd3..5dd18f5 100644 (file)
@@ -936,7 +936,7 @@ X.Dom.Node.prototype.css = function( nameOrObj /* orUnitID, valuOrUnitOrName */
        var XDomStyle = X.Dom.Style,
                args = arguments,
                css  = this._css,
-               p, valOrUnit, name, v, node, camelize, unit;
+               p, valOrUnit, name, v, camelize, unit;
        if( this._xnodeType !== 1 ) return this;
 // setter:object
        if( X.Type.isObject( nameOrObj ) ){
@@ -945,17 +945,9 @@ X.Dom.Node.prototype.css = function( nameOrObj /* orUnitID, valuOrUnitOrName */
                for( p in nameOrObj ){
                        css[ camelize( p ) ] = nameOrObj[ p ];
                };
-               this._cssText = XDomStyle.objToCssText( this._css );
-               if( node = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode ){
-                       if( this._cssText ){
-                               node.style.cssText = this._cssText;
-                               this._styleText = ' style="' + this._cssText + '"';
-                       } else {
-                               node.removeAttribute( 'style' );
-                               delete this._cssText;
-                               delete this._styleText;
-                       };
-               };
+               this._dirty |= X.Dom.Dirty.CSS;
+               this.parent && this._reserveUpdate();
+               delete this._cssText;
                return this;
        } else
        if( 1 < args.length ){
@@ -964,32 +956,16 @@ X.Dom.Node.prototype.css = function( nameOrObj /* orUnitID, valuOrUnitOrName */
                        if( !css ) css = this._css = {};
                        name = XDomStyle.camelize( nameOrObj );
                        v    = args[ 1 ];
-                       node = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;
                        if( css[ name ] === v ) return this;
                        if( !v && v !== 0 ){
                                delete css[ name ];
-                               if( node ){
-                                       node.style[ name ] = ''; // val
-                               };
-                               this._cssText = XDomStyle.objToCssText( css );
-                               if( !this._cssText ){
-                                       delete this._cssText;
-                                       delete this._styleText;
-                                       node && node.removeAttribute( 'style' );
-                               };
-                               return this;
-                       };
-                       if( node ){
-                               node.style[ name ] = v; // val
-                       };
-                       if( !css[ name ] ){
-                               this._cssText = [ this._cssText, this._cssText ? ';' : '', XDomStyle.uncamelize( nameOrObj ), ':', v ].join( '' );
-                               css[ name ] = v;
                        } else {
                                css[ name ] = v;
-                               this._cssText = XDomStyle.objToCssText( css );
                        };
-                       this._styleText = ' style="' + this._cssText + '"';
+                       delete this._cssText;
+                       this._dirty |= X.Dom.Dirty.CSS;
+                       // parent でなく this._root!
+                       this.parent && this._reserveUpdate();
                        return this;
                };
 // getter unit
@@ -1009,16 +985,14 @@ X.Dom.Node.prototype.css = function( nameOrObj /* orUnitID, valuOrUnitOrName */
 };
 
 X.Dom.Node.prototype.cssText = function( v ){
-       var camelize, obj, i, l, attr, name;
+       var obj, i, l, attr, name;
        if( X.Type.isString( v ) ){
-               camelize = X.Dom.Style.camelize;
                obj = {};
                v   = v.split( ';' );
                delete this._css;
                for( i = 0, l = v.length; i < l; ++i ){
                        attr = v[ i ].split( ':' );
-                       name = camelize( attr[ 0 ] );
-                       name && ( obj[ name ] = attr[ 1 ] || true );
+                       ( name = attr[ 0 ] ) && ( obj[ name ] = attr[ 1 ] || true );
                };
                return this.css( obj );
        };
@@ -1026,7 +1000,7 @@ X.Dom.Node.prototype.cssText = function( v ){
 };
 
 /*
- * ã\81\93ã\81\93ã\81§ã\81¯ HTMLElement ã\81\8bã\81®ã\83\81ã\83£ã\83\83ã\82¯ã\81¯è¡\8cã\82\8fã\81ªã\81\84ï¼\81
+ * ここでは HTMLElement のチャックは行わない!
  */
 X.Dom.Node.prototype._getCharSize =
        window.getComputedStyle ?
index 4894dc0..b5c3ce0 100644 (file)
@@ -62,3 +62,5 @@ X.Dom.NodeList.prototype.each = function( func ){
                };\r
        };\r
 })();\r
+\r
+\r
index 6796d0d..6af421b 100644 (file)
@@ -465,7 +465,7 @@ X.Dom.Query._parse = function( query, last ){
                        isNot   = false;\r
                        parsed  = null;\r
                        \r
-                       alert( '//end :' + ( xnodes && xnodes.length ) );\r
+                       console.log( '//end :' + ( xnodes && xnodes.length ) );\r
                };\r
                console.log( 'multi:' + ( xnodes && xnodes.length ) )\r
                \r
@@ -687,4 +687,5 @@ X.Dom.Query._filter = {
                        return res;\r
                }\r
        }\r
-};
\ No newline at end of file
+};\r
+\r
index 311de29..0a4a509 100644 (file)
@@ -10,7 +10,7 @@
                whiteSpace = '\t\r\n\f\b ';
 
        // Empty Elements - HTML 4.01
-       var empty = {area:1,base:1,basefont:1,br:1,col:1,frame:1,hr:1,img:1,input:1,isindex:1,link:1,meta:1,param:1,embed:1};
+       var empty = X.Dom.DTD.EMPTY;
 
        // Block Elements - HTML 4.01
        var block = {address:1,applet:1,blockquote:1,button:1,center:1,dd:1,del:1,dir:1,div:1,dl:1,dt:1,fieldset:1,form:1,frameset:1,hr:1,iframe:1,ins:1,isindex:1,li:1,map:1,menu:1,noframes:1,noscript:1,object:1,ol:1,p:1,pre:1,script:1,table:1,tbody:1,td:1,tfoot:1,th:1,thead:1,tr:1,ul:1};
@@ -22,6 +22,9 @@
        // (and which close themselves)
        var closeSelf = {colgroup:1,dd:1,dt:1,li:1,options:1,p:1,tbody:1,td:1,tfoot:1,th:1,thead:1,tr:1}; // add tbody
 
+       // todo:
+       var plainText = { plaintext : 1, xmp : 1 };
+
        var sisters = {
                th : { td : 1 },
                td : { th : 1 },
                        ++i;
                };
                if( phase === 9 ){
-                       if( parseStartTag( stack, last, handler, tagName /*.toLowerCase() */, attrs, empty, i ) === false ) return false;
+                       if( parseStartTag( stack, last, handler, tagName, attrs, empty, i ) === false ) return false;
                        return i;
                };
                return 0; // error
                        ++i;
                };
                if( phase === 9 ){
-                       parseEndTag( stack, handler, tagName ); //.toLowerCase()
+                       parseEndTag( stack, handler, tagName );
                        return i;
                };
                return 0; // error
        };
 
        function parseStartTag( stack, last, handler, tagName, attrs, unary, index ) {
-               if ( block[ tagName.toLowerCase() ] === 1 ) {
+               var tagLower = tagName.toLowerCase();
+               if ( block[ tagLower ] === 1 ) {
                        while ( last && inline[ last.toLowerCase() ] === 1 ) {
                                parseEndTag( stack, handler, last );
                                last = stack[ stack.length - 1 ];
                        };
                };
-               closeSelf[ tagName.toLowerCase() ] === 1 && ( last === tagName || ( sisters[ tagName.toLowerCase() ] && sisters[ tagName.toLowerCase() ][ last.toLowerCase() ] === 1 ) ) && parseEndTag( stack, handler, last );
-               unary = empty[ tagName.toLowerCase() ] === 1 || !!unary;
+               closeSelf[ tagLower ] === 1 && ( last === tagName || ( sisters[ tagLower ] && sisters[ tagLower ][ last.toLowerCase() ] === 1 ) ) && parseEndTag( stack, handler, last );
+               unary = empty[ tagLower ] === 1 || !!unary;
                !unary && ( stack[ stack.length ] = tagName );
                
                return handler.start( tagName, attrs, unary, index );
diff --git a/0.6.x/js/dom/20_XDomImage.js b/0.6.x/js/dom/20_XDomImage.js
new file mode 100644 (file)
index 0000000..4634101
--- /dev/null
@@ -0,0 +1,181 @@
+\r
+X.Dom.Image = {\r
+       _actualSize : {},\r
+       \r
+/*\r
+ * original\r
+ * LICENSE: MIT\r
+ * AUTHOR: uupaa.js@gmail.com\r
+ */    \r
+       getActualDimension : function( XnodeOrImageElemOrSrc ){\r
+               var xnode, img, remove, ret, run, memW, memH, w, h;\r
+       \r
+               if( X.Type.isString( XnodeOrImageElemOrSrc ) ){\r
+                       if( ret = X.Dom.Image._actualSize[ X.Dom.getAbsolutePath( XnodeOrImageElemOrSrc ) ] ) return ret;\r
+                       \r
+                       xnode = X.Dom.Node._systemNode.create(\r
+                               'img',\r
+                               {\r
+                                       src : XnodeOrImageElemOrSrc\r
+                               },\r
+                               {\r
+                                       position   : 'absolute'\r
+                               }\r
+                       );\r
+                       img    = xnode._ie4getRawNode ? xnode._ie4getRawNode() : xnode._rawNode;\r
+                       remove = true;\r
+               } else {\r
+                       if( XnodeOrImageElemOrSrc.constructor === X.Dom.Node ){\r
+                               xnode = XnodeOrImageElemOrSrc;\r
+                               img   = xnode._ie4getRawNode ? xnode._ie4getRawNode() : xnode._rawNode;\r
+                       } else\r
+                       if( X.Type.isHTMLElement( XnodeOrImageElemOrSrc ) ){\r
+                               img = XnodeOrImageElemOrSrc;\r
+                       } else {\r
+                               return;\r
+                       };\r
+                       if( ret = X.Dom.Image._actualSize[ img.src ] ) return ret;\r
+               };\r
+       \r
+               // for Firefox, Safari, Google Chrome\r
+               if( img.naturalWidth ) return [ img.naturalWidth, img.naturalHeight ];\r
+       \r
+               if( X.UA.IE && 5 <= X.UA.IE ){// for IE\r
+                       run  = img.runtimeStyle;\r
+                       memW = run.width;\r
+                       memH = run.height;\r
+       \r
+                       // keep runtimeStyle\r
+                       run.width  = 'auto';\r
+                       // override\r
+                       run.height = 'auto';\r
+                       w = img.width;\r
+                       h = img.height;\r
+                       run.width  = memW;\r
+                       // restore\r
+                       run.height = memH;\r
+               } else {// for Opera and Other\r
+       \r
+                       memW = img.width;\r
+                       memH = img.height;\r
+                       // keep current style\r
+                       img.removeAttribute( 'width' );\r
+                       img.removeAttribute( 'height' );\r
+                       w = img.width;\r
+                       h = img.height;\r
+                       img.width  = memW;\r
+                       // restore\r
+                       img.height = memH;\r
+               };\r
+               \r
+               ret = X.Dom.Image._actualSize[ img.src ] = [ w, h ];\r
+               \r
+               remove && xnode.destroy();\r
+               \r
+               return ret;\r
+       },\r
+       \r
+       /* \r
+        * original\r
+        *  LICENSE: MIT?\r
+        *  URL: http://d.hatena.ne.jp/uupaa/20080413/1208067631\r
+        *  AUTHOR: uupaa.js@gmail.com\r
+        * \r
+        */\r
+       Loader : X.EventDispatcher.inherits(\r
+               'ImageLoader',\r
+               X.Class.POOL_OBJECT,\r
+               {\r
+                       xnode   : null,\r
+                       size    : null,\r
+                       tick    : 0,\r
+                       timerID : 0,\r
+                       finish  : false,\r
+                       abspath : null,\r
+                       delay   : null,\r
+                       timeout : 0,\r
+                       Constructor : function( abspath, delay, timeout ){\r
+                               var img;\r
+                               \r
+                               this.abspath = abspath;\r
+                               this.delay   = delay;\r
+                               this.timeout = timeout;\r
+                               this.xnode =\r
+                                       (\r
+                                               window.Image ?\r
+                                                       X.Dom.Node( img = new Image() ) :\r
+                                                       X.Dom.Node._systemNode.create( 'img', { src : abspath } )\r
+                                       )\r
+                                       .listen( 'load', this )\r
+                                       .listen( 'error', this )\r
+                                       .listen( 'abort', this )\r
+                                       .listen( X.Dom.Event.LOAD_ASSET_COMPLETE, this )\r
+                                       .listen( X.Dom.Event.LOAD_ASSET_ERROR, this );\r
+       \r
+                               img && ( img.src = abspath );\r
+\r
+                               this._detect();\r
+                       },\r
+                       handleEvent : function( e ){\r
+                               var size;\r
+                               switch( e.type ){\r
+                                       case 'error' :\r
+                                       case 'abort' :\r
+                                               if( this.finish ) return;\r
+                                               this.finish = true;\r
+                                               this.timerID = this.asyncDispatch( 0, { type : X.Dom.Event.LOAD_ASSET_ERROR } );\r
+                                               break;\r
+                                       case 'load' :\r
+                                       // if( finish === true ) return; // これがあると firefox3.6 で駄目、、、\r
+                                       // if( timer ) return; // これがあると safari3.2 で駄目、、、\r
+                                               this.finish = true;\r
+                                               this.timerID && X.Timer.remove( this.timerID );\r
+                                               if( window.opera && !this.xnode._rawNode.complete ){\r
+                                                       this.timerID = this.asyncDispatch( 0, { type : X.Dom.Event.LOAD_ASSET_ERROR } );\r
+                                                       return;\r
+                                               };\r
+                                               size = X.Dom.Image.getActualDimension( X.UA.IE && X.UA.IE < 9 && window.Image ? this.abspath : this.xnode );\r
+                                               this.timerID = this.asyncDispatch( 0, {\r
+                                                       type : X.Dom.Event.LOAD_ASSET_COMPLETE,\r
+                                                       src  : this.abspath,\r
+                                                       w    : size[ 0 ],\r
+                                                       h    : size[ 1 ]\r
+                                               } );\r
+                                               break;\r
+                                       case X.Dom.Event.LOAD_ASSET_COMPLETE :\r
+                                       case X.Dom.Event.LOAD_ASSET_ERROR :\r
+                                               delete this.timerID;\r
+                                               X.Timer.once( 0, this, this.kill );\r
+                                               break;\r
+                               };\r
+                       },      \r
+                       _detect : function(){\r
+                               if( this.finish === true ) return;\r
+                               if( this.xnode._rawNode.complete ){\r
+                                       this.finish = true;\r
+                                       if( this.xnode._rawNode.width ) return;\r
+                                       this.timerID = this.asyncDispatch( 0, { type : X.Dom.Event.LOAD_ASSET_ERROR } );\r
+                                       return;\r
+                               };\r
+                               if( ( this.tick += this.delay ) > this.timeout ){\r
+                                       this.finish = true;\r
+                                       this.timerID = this.asyncDispatch( 0, { type : X.Dom.Event.LOAD_ASSET_ERROR } );\r
+                                       return;\r
+                               };\r
+                               this.timerID = X.Timer.once( this.delay, this, this._detect );\r
+                       },\r
+                       stop : function(){\r
+                               // if( this.dispatch( { type : X.Dom.Event.LOAD_BEFORE_STOP } ) & X.Callback.CANCEL_NOW ) return;\r
+                               \r
+                               // this.dispacth( { type : X.Dom.Event.LOAD_ASSET_STOPED } );\r
+                               this.kill();\r
+                       },\r
+                       onKill : function(){\r
+                               this.timerID && X.Timer.remove( this.timerID );\r
+                               this.xnode.destroy();\r
+                               this.unlisten();\r
+                       }\r
+               }\r
+       )\r
+};\r
+\r