OSDN Git Service

3096eed9e16e173791c89f5d655afc0c289a585d
[pettanr/clientJs.git] / 0.6.x / js / dom / 11_XDomNode.js
1 X.Dom.Dirty = {\r
2         CLEAN            :  0,\r
3         CHILD_IS_DIRTY   :  1,\r
4         ID               :  2, // width, height, x, y\r
5         CONTENT          :  4, // width, height, x, y textNode の内容\r
6         CLASSNAME        :  8, // _getCharSize, width, height, x, y\r
7         ATTR             : 16, // _getCharSize, width, height, x, y\r
8         CSS              : 32, // _getCharSize, width, height, x, y\r
9         IE_FILTER        : X.UA.IE && X.UA.IE < 9 && !X.UA.MacIE ? 64 : 0,\r
10         UNKNOWN_TAG_FIX  : 128,\r
11         IE4_TEXTNODE_FIX : 256\r
12 };\r
13 \r
14 X.Dom.State = {\r
15         DESTROYED          : 0,\r
16         EXIST              : 1,\r
17         BELONG_TREE        : 2,\r
18         DISPLAY_NONE       : 4,\r
19         DISPLAY_BLOCK      : 8,\r
20         DISPLAY_INLINE     : 16,\r
21         POSITION_ABSOLUTE  : 32,\r
22         OVERFLOW_HIDDEN    : 64,\r
23         HAS_WIDTH_LENGTH   : 128,\r
24         HAS_WIDTH_PERCENT  : 256,\r
25         HAS_HEIGHT_LENGTH  : 512,\r
26         HAS_HEIGHT_PERCENT : 1024,\r
27         IE4_ONLY_TEXT      : 2048,\r
28         IE5_DISPLAY_NONE_FIX : !X.UA.MacIE && 5 <= X.UA.IE && X.UA.IE < 5.5 ? 4096 : 0 // filterがかかっていると不可? MacIE5.2- は ?\r
29 };\r
30 \r
31 X.Dom._strictElmCreation = !X.UA.MacIE && X.UA.IE5678;// && !X.UA.MacIE;\r
32 \r
33 X.Dom._useDocumentFragment = document.createDocumentFragment && ( !X.UA.IE || 5.5 <= X.UA.IE ) && document.createDocumentFragment();\r
34 \r
35 /*\r
36  * Node( rawElement | rawTextnode | htmlString | textString )\r
37  */\r
38 \r
39 X.Dom.Node = X.EventDispatcher.inherits(\r
40         'XDomNode',\r
41         X.Class.POOL_OBJECT,\r
42         {\r
43                 _uid       : 0,\r
44                 _state     : 0,\r
45                 _dirty     : 0,\r
46                 \r
47                 _isNew     : false,\r
48                 \r
49                 _rawNode   : null,\r
50                 _root      : null, // xnode が文書ツリーに属しているか?はこれを見る\r
51                 parent     : null, // remove された枝も親子構造は維持している。\r
52                 _xnodes    : null,\r
53         \r
54                 _xnodeType : 0,\r
55                 _tag       : null,\r
56                 _text      : null,\r
57                 _id        : null,\r
58                 _className : '',\r
59 \r
60                 _attrs     : null, // X.Dom.Attr\r
61                 _newAttrs  : null,\r
62                 _attrText  : '', // X.Dom.Attr.objToAttrText が必要な場合は false が入っている\r
63                 \r
64                 _css       : null, // X.Dom.Style\r
65                 _cssText   : null,\r
66                 \r
67                 _fontSize  : 0,\r
68                 \r
69                 _anime     : null,\r
70                 \r
71                 Constructor : function( v ){\r
72                         var css, xnodes, xnode, parent, uid = Node._chashe.length;\r
73                         \r
74                         if( Node._newByTag ){\r
75                                 Node._newByTag  = false;\r
76                                 this._tag       = v.toUpperCase();\r
77                                 this._xnodeType = 1;\r
78                                 this._state     = X.Dom.State.DISPLAY_INLINE; // todo\r
79                                 arguments[ 1 ] && this.attr( arguments[ 1 ] );\r
80                                 css = arguments[ 2 ] || arguments[ 1 ];\r
81                                 css && this[ X.Type.isString( css ) ? 'cssText' : 'css' ]( css );\r
82                         } else\r
83                         if( Node._newByText ){\r
84                                 Node._newByText = false;\r
85                                 this._text      = v;\r
86                                 this._xnodeType = 3;\r
87                                 this._state     = X.Dom.State.DISPLAY_INLINE;\r
88                         } else {\r
89                                 if( 1 < arguments.length ) return new X.Dom.NodeList( arguments );\r
90                                 if( X.Type.isArray( v ) && v.length ) return new X.Dom.NodeList( v );\r
91                                 if( !this || this.append !== Node.prototype.append ) return new Node( v );\r
92                 \r
93                                 switch( Node._getType( v ) ){\r
94                                         case Node.IS_XNODE :\r
95                                         case Node.IS_XNODE_LIST :\r
96                                                 return v;\r
97                                         case Node.IS_RAW_HTML :\r
98                                                 if( xnode = Node._getXNode( v ) ) return xnode;\r
99                                                 // v.parentNode || v.parentElement : dom1 || dom0\r
100                                                 this.parent     = ( parent = v.parentNode || v.parentElement ) && parent.tagName /* ie7- */ && Node._getXNode( parent );\r
101                                                 this._root      = this.parent ? this.parent._root : null;\r
102                                                 this._rawNode   = v;\r
103                                                 this._xnodeType = 1;\r
104                                                 this._state     = X.Dom.State.DISPLAY_BLOCK; // todo\r
105                                                 this._tag       = v.tagName.toUpperCase();\r
106                                                 this._id        = v.id;\r
107                                                 this._className = v.className;\r
108                                                 this.cssText( v.style.cssText );\r
109                                                 // X.Dom.Dirty.CSS を落とす\r
110                                                 this._dirty = 0;\r
111                                                 // attr の回収は不可能、、、\r
112                                                 if( X.Dom.DOM_IE4 ){\r
113                                                         v.setAttribute( 'UID', '' + uid );\r
114                                                 } else {\r
115                                                         v.UID = uid;\r
116                                                 };\r
117                                                 // childNodes...\r
118                                                 break;\r
119                                         case Node.IS_RAW_TEXT :\r
120                                                 if( xnode = Node._getXNode( v ) ) return xnode;\r
121                                                 this.parent     = Node._getXNode( v.parentNode );\r
122                                                 this._root      = this.parent ? this.parent._root : null;\r
123                                                 this._rawNode   = v;\r
124                                                 this._xnodeType = 3;\r
125                                                 this._state     = X.Dom.State.DISPLAY_INLINE;\r
126                                                 this._text      = v.data;\r
127                                                 v.UID = uid;\r
128                                                 break;\r
129                                         case Node.IS_HTML_STRING :\r
130                                         case Node.IS_STRING :\r
131                                                 if( xnodes = X.Dom.parse( v, true ) && 1 < xnodes.length ) return new X.Dom.NodeList( xnodes );\r
132                                                 if( xnodes.length ) return xnodes[ 0 ];\r
133                                                 return Node.none;\r
134                                         case Node.IS_IMAGE :\r
135                                                 if( xnode = Node._getXNode( v ) ) return xnode;\r
136                                                 this._rawNode   = v;\r
137                                                 this._xnodeType = 4;\r
138                                                 v.UID           = uid;\r
139                                                 this._state     = X.Dom.State.EXIST;\r
140                                                 break;\r
141                                         case Node.IS_WINDOW :\r
142                                         case Node.IS_DOCUMENT :\r
143                                                 if( xnode = Node._getXNode( v ) ) return xnode;\r
144                                                 this._rawNode   = v;\r
145                                                 this._xnodeType = 2;\r
146                                                 this._state     = X.Dom.State.DISPLAY_BLOCK;\r
147                                                 break;\r
148                                         default :\r
149                                                 if( Node.none ) return Node.none;\r
150                                                 return;\r
151                                 };\r
152                         };\r
153                         \r
154                         Node._chashe[ this._uid = uid ] = this;\r
155                 }\r
156         }\r
157 );\r
158 \r
159 var Node = X.Dom.Node;\r
160 \r
161 Node.IS_XNODE       = 1;\r
162 Node.IS_RAW_HTML    = 2;\r
163 Node.IS_RAW_TEXT    = 3;\r
164 Node.IS_HTML_STRING = 4;\r
165 Node.IS_STRING      = 5;\r
166 //Node.IS_DOC_FRAG    = 6;\r
167 Node.IS_XNODE_LIST  = 7;\r
168 Node.IS_WINDOW      = 8;\r
169 Node.IS_DOCUMENT    = 9;\r
170 Node.IS_IMAGE       = 10;\r
171 \r
172 Node._getType = function( v ){\r
173         if( v === '' ) return Node.IS_STRING;\r
174         if( !v ) return 0;\r
175         if( v === window ) return Node.IS_WINDOW;\r
176         if( v === document ) return Node.IS_DOCUMENT;\r
177         if( v.constructor === window.Image ) return Node.IS_IMAGE;\r
178         if( X.UA.Safari && X.UA.Safari < 3 ){\r
179                 if( v.src !== undefined && v.onload !== undefined && X.Type.isNumber( v.height ) && X.Type.isNumber( v.width ) && X.Type.isBoolean( v.complete ) ){\r
180                         return Node.IS_IMAGE;\r
181                 };\r
182         };      \r
183         if( v.constructor === Node ) return Node.IS_XNODE;\r
184         if( v.constructor === X.Dom.NodeList ) return Node.IS_XNODE_LIST;\r
185         if( v.tagName ) return Node.IS_RAW_HTML;\r
186         if( v.nodeType === 3 ) return Node.IS_RAW_TEXT;\r
187         if( typeof v === 'string' ){\r
188                 return '<' === v.charAt( 0 ) && v.charAt( v.length - 1 ) === '>' ? Node.IS_HTML_STRING : Node.IS_STRING;\r
189         };\r
190         //if( v.nodeType === 11 ) return Node.IS_DOC_FRAG;\r
191         return 0;\r
192 };\r
193 Node._getXNode = function( v ){\r
194         var uid, i, chashe, xnode;\r
195         switch( Node._getType( v ) ){\r
196                 case Node.IS_XNODE :\r
197                 case Node.IS_XNODE_LIST :\r
198                         return v;\r
199                 case Node.IS_RAW_HTML :\r
200                 case Node.IS_IMAGE :\r
201                         // fake TextNode too.\r
202                         if( X.Dom.DOM_IE4 ){\r
203                                 uid = v.getAttribute( 'UID' );\r
204                                 return uid && Node._chashe[ uid ];\r
205                         };\r
206                         return v.UID && Node._chashe[ v.UID ];\r
207                 case Node.IS_WINDOW :\r
208                         return Node._window;\r
209                 case Node.IS_DOCUMENT :\r
210                         return Node._document;\r
211                 case Node.IS_RAW_TEXT :\r
212                         if( v.UID ) return Node._chashe[ v.UID ];\r
213                         for( chashe = Node._chashe, i = chashe.length; i; ){\r
214                                 if( ( xnode = Node._chashe[ --i ] ) && ( xnode._rawNode === v ) ) return xnode;\r
215                         };\r
216         };\r
217 };\r
218 \r
219 \r
220 Node.create = function( tag, opt_attrs, opt_css ){\r
221         var list, i;\r
222         switch( Node._getType( tag ) ){\r
223                 case Node.IS_STRING :\r
224                         Node._newByTag = true;\r
225                         return new Node( tag, opt_attrs, opt_css );\r
226                 case Node.IS_HTML_STRING :\r
227                         list = X.Dom.parse( tag, true );\r
228                         for( i = list.length; 1 < i; ){\r
229                                 list[ --i ].destroy();\r
230                         };\r
231                         return list[ 0 ];\r
232         };\r
233 };\r
234 Node.createText = function( text ){\r
235         Node._newByText = true;\r
236         return new Node( text );\r
237 };\r
238 \r
239 \r
240 Node.getRoot = function( xnode ){\r
241         return Node._document;\r
242         //return xNode._body._rawNode.documentElement ? node : node.ownerDocument || node.document;\r
243 };\r
244         // XMLかどうかを判別する\r
245 Node.isXmlDocument =\r
246         X.Dom.DOM_IE4 ?\r
247                 X.emptyFunction :\r
248                 (function( root ){\r
249                         if( X.Type.isBoolean( root.isXML ) ) return root.isXML;\r
250                         return root.isXML = root._rawNode.createElement( 'p' ).tagName !== root._rawNode.createElement( 'P' ).tagName;\r
251                 });\r
252 \r
253 Node._chashe     = [];\r
254 Node.none        = Node._chashe[ 0 ] = new Node();\r
255 Node._window     = new Node( window ); // Node._chashe[ 1 ]\r
256 Node._document   = new Node( document ); // Node._chashe[ 2 ]\r
257 Node._html       = null; // Node._chashe[ 3 ]\r
258 Node._body       = null;// = Node._chashe[ 4 ] body\r
259 Node._systemNode = null;// = Node._chashe[ ? ]\r
260 \r
261 Node._reserveRemoval = [];\r
262 \r
263 if( X.Dom.DOM_IE4 ){\r
264         Node.prototype._ie4getRawNode = function(){\r
265                 var elm = this._rawNode;\r
266                 return elm ||\r
267                         ( ( elm = document.all[ 'ie4uid' + this._uid ] ) && ( this._rawNode = elm ) ) ||\r
268                         ( this._id && ( elm = document.all[ this._id ] ) ) && ( this._rawNode = elm );\r
269         };\r
270 };\r
271 \r
272 \r
273 /* --------------------------------------\r
274  *  Create\r
275  */\r
276 Node.prototype.create = function( tag, opt_attrs, opt_css ){\r
277         var xnode;\r
278         if( this._xnodeType !== 1 ) return;\r
279         if( !this._xnodes ) this._xnodes = [];\r
280         \r
281         xnode = Node.create( tag, opt_attrs, opt_css );\r
282         \r
283         xnode.parent = this;\r
284         this._xnodes[ this._xnodes.length ] = xnode;\r
285         this._root && this._reserveUpdate();\r
286         return xnode;\r
287 };\r
288 \r
289 /* --------------------------------------\r
290  *  CreateText\r
291  */\r
292 Node.prototype.createText = function( text ){\r
293         var xnode;\r
294         if( this._xnodeType !== 1 ) return;\r
295         if( !this._xnodes ) this._xnodes = [];\r
296         \r
297         Node._newByText = true;\r
298         xnode = new Node( text );\r
299         xnode.parent = this;\r
300         \r
301         this._root && this._reserveUpdate();\r
302         this._xnodes[ this._xnodes.length ] = xnode;\r
303         return xnode;\r
304 };\r
305 \r
306 /* --------------------------------------\r
307  *  Clone\r
308  * http://d.hatena.ne.jp/think49/20110724/1311472811\r
309  * http://d.hatena.ne.jp/uupaa/20100508/1273299874\r
310  */\r
311 Node.prototype.clone = function( opt_clone_children ){\r
312         var xnode, xnodes, i, l;\r
313         switch( this._xnodeType ){\r
314                 case 1 :\r
315                         Node._newByTag = true;\r
316                         xnode = new Node( this._tag, X.cloneObject( this._attrs ), X.cloneObject( this._css ) )\r
317                                 .attr( { 'id' : this._id } )\r
318                                 .className( this._className );\r
319                         if( opt_clone_children && ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
320                                 for( i = 0; i < l; ++i ){\r
321                                         xnode.append( xnodes[ i ].clone( true ) );\r
322                                 };\r
323                         };\r
324                         return xnode;\r
325                 case 3 :\r
326                         Node._newByText = true;\r
327                         xnode = new Node( this._text );\r
328                         return xnode;\r
329                 \r
330                 //case 0 :\r
331                 //case 2 :\r
332         };\r
333         return this;\r
334 };\r
335 \r
336 /* --------------------------------------\r
337  *  Add\r
338  * Node\r
339  * HtmlElement の場合は内部使用専用 そのため event の破棄等しない\r
340  */\r
341 Node.prototype.append = function( v ){\r
342         var i, l, xnodes, frg;\r
343         if( this._xnodeType !== 1 ) return;\r
344         \r
345         if( 1 < ( l = arguments.length ) ){\r
346                 for( i = 0; i < l; ++i ){\r
347                         this.append( arguments[ i ] );\r
348                 };\r
349                 return this;\r
350         };\r
351         \r
352         if( !( xnodes = this._xnodes ) ) this._xnodes = xnodes = [];\r
353         \r
354         switch( Node._getType( v ) ){\r
355                 case Node.IS_RAW_HTML :\r
356                 case Node.IS_RAW_TEXT :\r
357                         v = new Node( v );\r
358                         break;\r
359                 case Node.IS_HTML_STRING :\r
360                 case Node.IS_STRING :\r
361                         return this.append.apply( this, X.Dom.parse( v, true ) );\r
362                 case Node.IS_XNODE :\r
363                         if( v._xnodeType !== 1 && v._xnodeType !== 3 ) return this;\r
364                         // 親の xnodes から v を消す\r
365                         if( v.parent ){\r
366                                 //if( X.Dom.DOM_W3C ){\r
367                                 //      v.parent._xnodes.splice( v.parent._xnodes.indexOf( v ), 1 );\r
368                                 //} else\r
369                                 //if( X.Dom.DOM_IE4 ){\r
370                                         v.remove();\r
371                                 //} else {\r
372                                         \r
373                                 //};\r
374                         };// else\r
375                         //if( ( i = Node._reserveRemoval.indexOf( v ) ) !== -1 ){\r
376                         //      if( !this._state ) alert( 'xnode already destroyed!' );\r
377                         //      Node._reserveRemoval.splice( i, 1 );\r
378                         //};\r
379                         break;\r
380                 default :\r
381                         return this;\r
382         };\r
383 \r
384         v.parent = this;\r
385         xnodes[ xnodes.length ] = v;\r
386         this._root && this._reserveUpdate();\r
387         return this;\r
388 };\r
389 \r
390 \r
391 Node.prototype.appendAt = function( start, v ){\r
392         var xnodes, l, i;\r
393         \r
394         if( this._xnodeType !== 1 ) return this;\r
395         \r
396         l = arguments.length;\r
397         if( !( xnodes = this._xnodes ) ) xnodes = this._xnodes = [];\r
398         \r
399         if( xnodes.length <= start ){\r
400                 if( l === 2 ) return this.append( v );\r
401                 for( i = 1; i < l; ++i ){\r
402                         this.append( arguments[ i ] );\r
403                 };\r
404                 return this;\r
405         };\r
406         if( start < 0 ) start = 0;\r
407         if( 2 < l ){\r
408                 for( ; l; ){\r
409                         this.appendAt( start, arguments[ --l ] );\r
410                 };\r
411                 return this;\r
412         };\r
413 \r
414         switch( Node._getType( v ) ){\r
415                 case Node.IS_RAW_HTML :\r
416                 case Node.IS_RAW_TEXT :\r
417                         v = new Node( v );\r
418                         break;\r
419                 case Node.IS_HTML_STRING :\r
420                 case Node.IS_STRING :\r
421                         v = X.Dom.parse( v, true );\r
422                         for( i = v.length; i; ){\r
423                                 this.appendAt( start, v[ --i ] );\r
424                         };\r
425                         return this;\r
426                 case Node.IS_XNODE :\r
427                         if( v._xnodeType !== 1 && v._xnodeType !== 3 ) return this;\r
428                         // 親の xnodes から v を消す\r
429                         if( v.parent ){\r
430                                 //if( X.Dom.DOM_W3C ){\r
431                                 //      v.parent._xnodes.splice( v.parent._xnodes.indexOf( v ), 1 );\r
432                                 //} else\r
433                                 //if( X.Dom.DOM_IE4 ){\r
434                                         v.remove();\r
435                                 //} else {\r
436                                         \r
437                                 //};\r
438                         };// else\r
439                         //if( ( i = Node._reserveRemoval.indexOf( v ) ) !== -1 ){\r
440                         //      if( !this._state ) alert( 'xnode already destroyed!' );\r
441                         //      Node._reserveRemoval.splice( i, 1 );\r
442                         //};\r
443                         break;\r
444                 default :\r
445                         return this;\r
446         };\r
447 \r
448         v.parent = this;\r
449         this._xnodes.splice( start, 0, v );\r
450         this._root && this._reserveUpdate();\r
451         return this;\r
452 };\r
453 \r
454 Node.prototype.appendTo = function( parent, opt_index ){\r
455         switch( Node._getType( parent ) ){\r
456                 case Node.IS_RAW_HTML :\r
457                         parent = new Node( parent );\r
458                         break;\r
459                 case Node.IS_HTML_STRING :\r
460                         parent = X.Dom.parse( parent, true );\r
461                         parent = parent[ 0 ] || parent;\r
462                 case Node.IS_XNODE :\r
463                         break;\r
464                 default :\r
465                         return this;\r
466         };\r
467         opt_index === undefined ? parent.append( this ) : parent.appendAt( opt_index, this );\r
468         return this;\r
469 };\r
470 \r
471 Node.prototype.appendToRoot = function( opt_index ){\r
472         opt_index === undefined ? Node._body.append( this ) : Node._body.appendAt( opt_index, this );\r
473         return this;\r
474 };\r
475 \r
476 /* --------------------------------------\r
477  *  Before , After, Replace\r
478  */\r
479 Node.prototype.before = function( v ){\r
480         var parent, l, start;\r
481         if( !( parent = this.parent ) ) return this;\r
482         \r
483         l = arguments.length;\r
484         start = this.getOrder();\r
485         if( 1 < l ){\r
486                 for( ; l; ){\r
487                         parent.appendAt( start, arguments[ --l ] );\r
488                 };\r
489                 return this;\r
490         };\r
491         parent.appendAt( start, v );\r
492         return this;\r
493 };\r
494 \r
495 Node.prototype.after = function( v ){\r
496         var parent, l, i, start;\r
497         if( !( parent = this.parent ) ) return this;\r
498         \r
499         l = arguments.length;\r
500         start = this.getOrder() + 1;\r
501         if( parent._xnodes.length <= start ){\r
502                 if( 1 < l ){\r
503                         for( i = 0; i < l; ++i ){\r
504                                 parent.append( arguments[ i ] );\r
505                         };\r
506                         return this;\r
507                 };\r
508                 parent.append( v );\r
509                 return this;\r
510         };\r
511         if( 1 < l ){\r
512                 for( ; l; ){\r
513                         parent.appendAt( start, arguments[ --l ] );\r
514                 };\r
515                 return this;\r
516         };\r
517         parent.appendAt( start, v );\r
518         return this;\r
519 };\r
520 \r
521 Node.prototype.replace = function( v ){\r
522         if( !this.parent ) return this;\r
523         return arguments.length === 1 ? this.before( v ).remove() : this.before.apply( this, arguments ).remove();\r
524 };\r
525 \r
526 /* --------------------------------------\r
527  *  Remove\r
528  */\r
529 Node.prototype.remove = function(){\r
530         var parent = this.parent;\r
531         \r
532         if( !parent ) return this;\r
533 \r
534         parent._xnodes.splice( parent._xnodes.indexOf( this ), 1 );\r
535         if( this._root ){\r
536                 Node._reserveRemoval[ Node._reserveRemoval.length ] = this;\r
537                 this._reserveUpdate();\r
538         };\r
539         delete this.parent;\r
540         delete this._root;\r
541         return this;\r
542 };\r
543 \r
544 Node.prototype.empty = function(){\r
545         var xnodes = this._xnodes, i;\r
546         if( xnodes && ( i = xnodes.length ) ){\r
547                 for( ; i; ){\r
548                         xnodes[ --i ].destroy();\r
549                 };\r
550                 xnodes.length = 0;\r
551         };\r
552         return this;\r
553 };\r
554 \r
555 /* --------------------------------------\r
556  *  destory\r
557  */\r
558 Node.prototype.destroy = function( isChild ){\r
559         var xnodes = this._xnodes, i, elm;\r
560         \r
561         if( !this._state ) return;\r
562         \r
563         elm = this._rawNode || this._ie4getRawNode && this._ie4getRawNode();\r
564         \r
565         if( xnodes && ( i = xnodes.length ) ){\r
566                 //for( ; i; ){\r
567                 //      xnodes[ --i ].destroy( true );\r
568                 //};\r
569         };\r
570         elm && this._listeners && this.unlisten(); // イベントの退避\r
571 \r
572         delete Node._chashe[ this._uid ];\r
573         delete this._state;\r
574         \r
575         if( this._root ){\r
576                 !isChild && this.remove();\r
577         } else {\r
578                 this.parent && this.parent._xnodes.splice( this.parent._xnodes.indexOf( this ), 1 );\r
579                 elm && !isChild && this._actualRemove();\r
580                 this.kill();\r
581         };\r
582 };\r
583 \r
584 \r
585 \r
586 /* --------------------------------------\r
587  *  contains\r
588  */\r
589 Node.prototype.contains = function( v ){\r
590         var elm, type, xnodes, i;\r
591         if( !v || this._xnodeType !== 1 ) return false;\r
592         // contains ie4+\r
593         if( ( elm = this._rawNode || this._ie4getRawNode && this._ie4getRawNode() ) && document.contains && ( type = Node._getType( v ) ) && ( type === Node.IS_RAW_HTML || type === Node.IS_RAW_TEXT ) ){\r
594                 return elm.contains( v );       \r
595         };\r
596         //if( document.compareDocumentPosition ){\r
597         //      \r
598         //};\r
599         xnodes = this._xnodes;\r
600         if( xnodes.indexOf( v ) !== -1 ) return true;\r
601         if( elm === v.parentNode ) return false;\r
602         for( i = xnodes.length; i; ){\r
603                 if( xnodes[ --i ].contains( v ) ) return true;\r
604         };\r
605         return false;\r
606 };\r
607 \r
608 /* --------------------------------------\r
609  *  getChild\r
610  */\r
611 Node.prototype.getChildAt = function( i ){\r
612         var xnodes = this._xnodeType === 1 && this._xnodes;\r
613         return xnodes && 0 <= i && i < xnodes.length && xnodes[ i ];\r
614 };\r
615 \r
616 \r
617 /* --------------------------------------\r
618  *  prevNode, nextNode, firstChild, lastChild\r
619  */\r
620 \r
621 Node.prototype.prevNode = function(){\r
622         var parent = this.parent, xnodes, index;\r
623         if( !parent ) return;\r
624         xnodes = parent._xnodes;\r
625         index = xnodes.indexOf( this );\r
626         if( 0 < index ) return xnodes[ index - 1 ];\r
627 };\r
628 Node.prototype.nextNode = function(){\r
629         var parent = this.parent, xnodes, index;\r
630         if( !parent ) return;\r
631         xnodes = parent._xnodes;\r
632         index  = xnodes.indexOf( this );\r
633         if( index + 1 < xnodes.length ) return xnodes[ index + 1 ];\r
634 };\r
635 Node.prototype.firstChild = function(){\r
636         return this.getChildAt( 0 );\r
637 };\r
638 Node.prototype.lastChild = function(){\r
639         return this.getChildAt( this._xnodes.length - 1 );\r
640 };\r
641 \r
642 /* --------------------------------------\r
643  *  getOrder\r
644  */\r
645 Node.prototype.getOrder = function(){\r
646         var parent = this.parent;\r
647         if( !parent ) return -1;\r
648         return parent._xnodes.indexOf( this );\r
649 };\r
650 \r
651 /* --------------------------------------\r
652  *  className, addClass, removeClass, hasClass\r
653  */\r
654 Node.prototype.className = function( v ){\r
655         var node, _, __;\r
656         // getter\r
657         if( v === undefined ) return this._className;\r
658         \r
659         // setter\r
660         if( this._className === v ) return this;\r
661         if( !v || typeof v !== 'string' ){\r
662                 delete this._className;\r
663         } else {\r
664                 // cleanup\r
665                 _  = ' ';\r
666                 __ = '  ';\r
667                 while( v.indexOf( __ ) !== -1 ){ v = v.split( __ ).join( _ ); };\r
668                 v.charAt( 0 ) === _ && ( v = v.substr( 1 ) );\r
669                 v.lastIndexOf( _ ) === 0 && ( v = v.substr( 0, v.length - 1 ) );\r
670                 \r
671                 if( this._className === v ) return this;\r
672                 v ? ( this._className = v ) : delete this._className;\r
673         };\r
674         this._dirty |= X.Dom.Dirty.CLASSNAME;\r
675         this._root && this._reserveUpdate();\r
676         return this;\r
677 };\r
678 Node.prototype.addClass = function( v ){\r
679         var names = v.split( ' ' ),\r
680                 i     = names.length,\r
681                 name;\r
682         v = '';\r
683         for( ; i; ){\r
684                 name = names[ --i ];\r
685                 if( !name ) continue;\r
686                 !this.hasClass( name ) && ( v += ( v ? ' ' : '' ) + name );\r
687         };\r
688         return v ? this.className( this._className + ( this._className ? ' ' : '' ) + v ) : this;\r
689 };\r
690 Node.prototype.removeClass = function( v ){\r
691         var _          = ' ',\r
692                 className  = this._className,\r
693                 names      = v.split( ' ' ),\r
694                 classNames, i, f, j;\r
695         if( !className ) return this;\r
696         for( classNames = className.split( _ ), i = classNames.length; i; ){\r
697                 className = classNames[ --i ];\r
698                 for( j = names.length; j; ){\r
699                         if( className === names[ --j ] ){\r
700                                 classNames.splice( i, 1 );\r
701                                 names.splice( j, 1 );\r
702                                 f = true;\r
703                                 break;\r
704                         };\r
705                 };\r
706         };\r
707         return f ? this.className( classNames.join( ' ' ) ) : this;\r
708 };\r
709 Node.prototype.toggleClass = function( v ){\r
710 \r
711 };\r
712 Node.prototype.hasClass = function( v ){\r
713         var _ = ' ',\r
714                 className = this._className,\r
715                 i, name;\r
716         if( className === v ) return true;\r
717         if( !className ) return false;\r
718         \r
719         className = _ + className + _;\r
720         if( className.indexOf( _ + v + _ ) !== -1 ) return true; // lucky hit\r
721         \r
722         for( v = v.split( _ ), i = v.length; i; ){\r
723                 name = v[ --i ];\r
724                 if( name === '' ) continue;\r
725                 if( className.indexOf( _ + name + _ ) === -1 ) return false;\r
726         };\r
727         return true;\r
728 };\r
729 \r
730 /* --------------------------------------\r
731  *  html, text\r
732  */\r
733 \r
734 Node._outerFlag = null;\r
735 \r
736 Node.prototype.html = function( html ){\r
737         var _ = '', q = '"', xnodes, n, i, l;\r
738         // setter\r
739         if( X.Type.isString( html ) ){\r
740                 if( this._xnodeType === 3 ) return this.text( html );\r
741                 return html ? this.empty().append.apply( this, X.Dom.parse( html, true ) ) : this.empty();\r
742         };\r
743         \r
744         // getter\r
745         if( this._xnodeType === 3 ){\r
746                 return this._text;\r
747         };\r
748         \r
749         if( this._dirty & X.Dom.Dirty.CSS && !( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
750                 delete this._cssText;\r
751         };\r
752         html = !Node._outerFlag ? [] : [\r
753                 '<', this._tag,\r
754                 this._id ? ' id="' + this._id + q : _,\r
755                 this._className ? ' class="' + this._className + q : _,\r
756                 this._attrText === false ? ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ) : this._attrText,\r
757                 this._cssText ? ' style="' + this._cssText + q : _,\r
758         '>' ];\r
759         \r
760         n = html.length;\r
761         if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
762                 if( !Node._outerFlag ) Node._outerFlag = this;\r
763                 for( i = 0; i < l; ++i ){\r
764                         html[ n ] = xnodes[ i ].html();\r
765                         ++n;\r
766                 };\r
767                 if( Node._outerFlag === this )  Node._outerFlag = null;\r
768         };\r
769         !Node._outerFlag || X.Dom.DTD.EMPTY[ this._tag ] || ( html[ n ] = '<\/' + this._tag + '>' );\r
770         return html.join( _ );\r
771 };\r
772 \r
773 Node.prototype.text = function( text ){\r
774         var xnodes, texts, i, l;\r
775         // setter\r
776         if( X.Type.isString( text ) ){\r
777                 if( this._xnodeType === 3 ){\r
778                         if( this._text !== text ){\r
779                                 text ? ( this._text = text ) : delete this.text;\r
780                                 this._root && this._reserveUpdate();\r
781                                 this._dirty |= X.Dom.Dirty.CONTENT;\r
782                         };\r
783                         return this;\r
784                 };\r
785                 if( !text ) return this.empty();\r
786                 if( ( xnodes = this._xnodes ) && xnodes.length === 1 && xnodes[ 0 ]._xnodeType === 3 ){\r
787                         xnodes[ 0 ].text( text );\r
788                         return this;\r
789                 };\r
790                 this.empty().createText( text );\r
791                 return this;\r
792         };\r
793         // getter\r
794         if( this._xnodeType === 1 ){\r
795                 if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
796                         for( texts = [], i = 0; i < l; ++i ){\r
797                                 texts[ i ] = xnodes[ i ].text();\r
798                         };\r
799                         return texts.join( '' );\r
800                 };\r
801                 return '';\r
802         };\r
803         return this._text;\r
804 };\r
805 \r
806 Node.prototype.each = function( func ){\r
807         func.call( this, 0 );\r
808         return this;\r
809 };\r
810 \r
811 \r
812 /* --------------------------------------\r
813  *  Async commit update\r
814  * \r
815  * state:\r
816  *  0 : no_rawnode\r
817  *  1 : not_added\r
818  *  3 : dirty\r
819  *  4 : clean\r
820  * \r
821  * remove :\r
822  * root._reserveRemoval = [] に追加。commitUpdate で remove して state は not_added\r
823  * add :\r
824  * root._reserveRemoval にいたら消す, new_parent._xnodes に挿入 steta は not_added にして commitUpdate を待つ\r
825  */\r
826         \r
827 Node.prototype._reserveUpdate = function(){\r
828         var root = Node._body;\r
829         if( root && !root._updateTimerID ) root._updateTimerID = X.Timer.requestFrame( root, root._startUpdate );\r
830 };\r
831 \r
832 Node.prototype._startUpdate = function(){\r
833         var removal, i, xnode, tmp;\r
834         if( X.Dom.readyState < X.Dom.Event.DOM_INIT ){\r
835                 return;\r
836         };\r
837         if( this._updateTimerID ){\r
838                 //X.Timer.cancelFrame( this._updateTimerID ); // fire 中の cancel が動かない、、、\r
839                 this._updateTimerID = 0;\r
840         } else {\r
841                 return;\r
842         };\r
843         // このイベントでサイズを取ると無限ループに\r
844         // X.Dom._listeners && X.Dom._listeners[ X.Dom.Event.BEFORE_UPDATE ] && X.Dom.dispatch( { type : X.Dom.Event.BEFORE_UPDATE } );\r
845 \r
846         removal = Node._reserveRemoval;\r
847         \r
848         tmp = this._rawNode.style.visibility;\r
849         //this._rawNode.style.visibility = 'hidden';\r
850 \r
851         //console.log( '_actualRemove().' );\r
852 \r
853         if( i = removal.length ){\r
854                 for( ; i; ){\r
855                         xnode = removal[ --i ];\r
856                         xnode._actualRemove();\r
857                         !this._state && xnode.kill();\r
858                 };\r
859                 removal.length = 0;\r
860         };\r
861 \r
862         //console.log( 'start _startUpdate().' );\r
863 \r
864         Node._html._dirty ? Node._html._commitUpdate() : this._commitUpdate();\r
865         \r
866         //console.log( 'end of _startUpdate().' );\r
867         \r
868         X.Dom._listeners && X.Dom._listeners[ X.Dom.Event.AFTER_UPDATE ] && X.Dom.asyncDispatch( 0, { type : X.Dom.Event.AFTER_UPDATE } );\r
869         //this._rawNode.style.visibility = tmp;\r
870 };\r
871 \r
872 Node.prototype._commitUpdate =\r
873         X.Dom.DOM_W3C ?\r
874                 ( function( parentElement, nextElement ){\r
875                         var elm = this._rawNode,\r
876                                 xnodes, l, i, frg, next, k, v;\r
877 \r
878                         if( this._state & X.Dom.State.IE5_DISPLAY_NONE_FIX ){\r
879                                 //alert( this._tag + ' ' + !!elm );\r
880                                 elm && elm.parentNode && this._actualRemove();\r
881                                 return nextElement;\r
882                         };\r
883 \r
884                         if( !elm || ( parentElement && elm.parentNode !== parentElement ) || ( nextElement && elm.nextSibling !== nextElement ) ){\r
885                                 nextElement ?\r
886                                         parentElement.insertBefore( this._actualCreate(), nextElement ) :\r
887                                         parentElement.appendChild( this._actualCreate() );\r
888                                 this._afterActualCreate();\r
889 \r
890                                 return elm || this._rawNode;\r
891                         } else\r
892                         if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ) {\r
893                                 \r
894                                 /*if( elm.childNodes.length !== l && ( frg = X.Dom._useDocumentFragment ) ){\r
895                                         for( i = 0; i < l; ++i ){\r
896                                                 frg.appendChild( xnodes[ i ]._actualCreate( true ) );\r
897                                         };\r
898                                         elm.appendChild( frg );\r
899                                         for( i = 0; i < l; ++i ){\r
900                                                 xnodes[ i ]._afterActualCreate( true );\r
901                                         };\r
902                                 } else {*/\r
903                                         for( ; l; ){\r
904                                                 next = xnodes[ --l ]._commitUpdate( elm, next );\r
905                                         };\r
906                                 //};\r
907                         };\r
908 \r
909                         delete this._fontSize;\r
910                         this._dirty && this._updateRawNode( elm );\r
911                         if( this._state & X.Dom.State.IE5_DISPLAY_NONE_FIX ){\r
912                                 return nextElement;\r
913                         };\r
914                         return elm;\r
915                 }) :\r
916         X.Dom.DOM_IE4 ? \r
917                 ( function( parentElement, prevElement ){\r
918                         var elm    = this._rawNode || this._ie4getRawNode(),\r
919                                 xnodes, l, i, html, text, prev;\r
920 \r
921                         if( !elm ){\r
922                                 prevElement ?\r
923                                         prevElement.insertAdjacentHTML( 'AfterEnd', this._actualCreate() ) :\r
924                                         parentElement.insertAdjacentHTML( 'AfterBegin', this._actualCreate() );\r
925                                 this._afterActualCreate();\r
926                                 return this._rawNode || this._ie4getRawNode();\r
927                         };\r
928                         \r
929                         xnodes = this._xnodes;\r
930                         l      = xnodes ? xnodes.length : 0;\r
931                         \r
932                         if( this._dirty & X.Dom.Dirty.IE4_TEXTNODE_FIX || ( this._state & X.Dom.State.IE4_ONLY_TEXT && ( l !== 1 || xnodes[ 0 ]._xnodeType !== 3 ) ) ){ // 1 < l && elm.children.length === 0\r
933                                 html = [];\r
934                                 for( i = 0; i < l; ++i ){\r
935                                         html[ i ] = xnodes[ i ]._actualCreate();\r
936                                 };\r
937                                 elm.innerHTML = html.join( '' );\r
938                                 for( i = 0; i < l; ++i ){\r
939                                         xnodes[ i ]._afterActualCreate();\r
940                                 };\r
941                                 this._state &= ~X.Dom.State.IE4_ONLY_TEXT;\r
942                         } else\r
943                         if( this._state & X.Dom.State.IE4_ONLY_TEXT ){ // textNode が swap した場合の検出は、_root で行う\r
944                                 text = xnodes[ 0 ];\r
945                                 if( text._dirty || !text._root ){\r
946                                         elm.innerHTML = text._text;\r
947                                         delete text._dirty;\r
948                                         text._root = this._root;                                        \r
949                                 };\r
950                         } else\r
951                         if( l ){\r
952                                 for( i = 0; i < l; ++i ){\r
953                                         prev = xnodes[ i ]._commitUpdate( elm, prev );\r
954                                 };\r
955                         };\r
956                         \r
957                         delete this._fontSize;\r
958                         this._dirty && this._updateRawNode( elm );\r
959                         return elm;\r
960                 }) :\r
961                 (function(){});\r
962 \r
963 Node.prototype._updateRawNode =\r
964         X.Dom.DOM_W3C ?\r
965                 ( function( elm ){\r
966                         var attrs, rename, k, v;\r
967 \r
968                         // textNode\r
969                         if( this._dirty & X.Dom.Dirty.CONTENT ){\r
970                                 elm.data = X.Dom.chrReferanceTo( this._text );\r
971                                 delete this._dirty;\r
972                                 return;\r
973                         };\r
974                         // id\r
975                         if( this._dirty & X.Dom.Dirty.ID ){\r
976                                 this._id ? ( elm.id = this._id ) : ( elm.id && elm.removeAttribute( 'id' ) );           \r
977                         };\r
978                         // className\r
979                         if( this._dirty & X.Dom.Dirty.CLASSNAME ){\r
980                                 this._className ? ( elm.className = this._className ) : ( elm.className && elm.removeAttribute( X.UA.IE ? 'className' : 'class' ) );                                    \r
981 \r
982                                 // ie5 only\r
983                                 if( X.Dom.State.IE5_DISPLAY_NONE_FIX && elm.currentStyle.display === 'none' ){\r
984                                         this._actualRemove();\r
985                                         this._state |= X.Dom.State.IE5_DISPLAY_NONE_FIX;\r
986                                         return;\r
987                                 };\r
988                         };\r
989                         // style\r
990                         if( this._dirty & X.Dom.Dirty.CSS ){\r
991                                 if( this._cssText !== null || ( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
992                                         X.UA.Opera78 || X.UA.NN6 ?\r
993                                                 elm.setAttribute( 'style', this._cssText ) : // opera8用\r
994                                                 ( elm.style.cssText = this._cssText );\r
995                                 } else {\r
996                                         elm.style.cssText = ''; // IE5.5以下 Safari3.2 で必要\r
997                                         elm.removeAttribute( 'style' );\r
998                                         delete this._cssText;\r
999                                 };\r
1000                         };\r
1001                         \r
1002                         if( this._dirty & X.Dom.Dirty.IE_FILTER ){\r
1003                                 elm.style.filter = X.Dom.Style.SPECIAL_FIX( this._css );\r
1004                         };\r
1005                         \r
1006                         // attr\r
1007                         if( this._dirty & X.Dom.Dirty.ATTR && ( attrs = this._newAttrs || this._attrs ) ){\r
1008                                 rename = X.Dom.Attr.renameForDOM;\r
1009                                 for( k in attrs ){\r
1010                                         if( !X.UA.MacIE && 5 <= X.UA.IE && X.UA.IE < 6 ){ // IETester 5.5 ではエラーが出なかった.MultipulIE5.5 ではエラーが出たので\r
1011                                                 if( this._tag === 'TEXTAREA' && k === 'value' ){\r
1012                                                         elm.firstChild ?\r
1013                                                                 ( elm.firstChild.data = attrs[ k ] ) :\r
1014                                                                 elm.appendChild( document.createTextNode( attrs[ k ] ) );\r
1015                                                         continue;\r
1016                                                 };\r
1017                                         };\r
1018                                         k = \r
1019                                         ( v = attrs[ k ] ) === undefined ?\r
1020                                                 elm.removeAttribute( rename[ k ] || k ) :\r
1021                                                 ( elm[ rename[ k ] || k ] = X.Dom.Attr.noValue[ k ] ? k : v );                          \r
1022 \r
1023                                 };\r
1024                                 delete this._newAttrs;\r
1025                         };\r
1026                         \r
1027                         delete this._dirty;\r
1028                 }) :\r
1029         X.Dom.DOM_IE4 ? \r
1030                 ( function( elm ){\r
1031                         var attrs, rename, k, v;\r
1032 \r
1033                         // fake textNode\r
1034                         if( this._dirty & X.Dom.Dirty.CONTENT ){\r
1035                                 elm.innerText = this._text;\r
1036                                 delete this._dirty;\r
1037                                 return;\r
1038                         };\r
1039                         \r
1040                 /*\r
1041                  * http://www.tohoho-web.com/js/element.htm\r
1042                  * title、className、id、lang、language には setAttribute でなく、element.id で直接読み書きできる\r
1043                  */     \r
1044                         // id\r
1045                         if( this._dirty & X.Dom.Dirty.CONTENT ) elm.setAttribute( 'id', this._id || ( 'ie4uid' + xnode._uid ) );\r
1046 \r
1047                         // className\r
1048                         if( this._dirty & X.Dom.Dirty.CLASSNAME ){\r
1049                                 this._className ? ( elm.className = this._className ) : elm.removeAttribute( 'class' );\r
1050                         };\r
1051                         // style\r
1052                         if( this._dirty & X.Dom.Dirty.CSS ){\r
1053                                 if( this._cssText !== null || ( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
1054                                         elm.style.cssText = this._cssText;\r
1055                                 } else {\r
1056                                         elm.style.cssText = '';\r
1057                                         elm.removeAttribute( 'style' );\r
1058                                         delete this._cssText;\r
1059                                 };\r
1060                         };\r
1061                         \r
1062                         if( this._dirty & X.Dom.Dirty.IE_FILTER ){\r
1063                                 this._rawNode.style.filter = X.Dom.Style.SPECIAL_FIX( this._css );\r
1064                         };\r
1065                         \r
1066                         // attr\r
1067                         if( this._dirty & X.Dom.Dirty.ATTR && ( attrs = this._newAttrs || this._attrs ) ){\r
1068                                 rename = X.Dom.Attr.renameForDOM;\r
1069                                 for( k in attrs ){\r
1070                                         ( v = attrs[ k ] ) === undefined ?\r
1071                                                 elm.removeAttribute( rename[ k ] || k ) :\r
1072                                                 elm.setAttribute( rename[ k ] || k, v ); // TODO X.Dom.Attr.noValue\r
1073                                 };\r
1074                                 delete this._newAttrs;\r
1075                         };\r
1076                         \r
1077                         delete this._dirty;\r
1078                 }) :\r
1079                 (function(){});\r
1080 \r
1081 /* --------------------------------------\r
1082  *  Create\r
1083  * \r
1084  * http://d.hatena.ne.jp/uupaa/20080718/1216362040\r
1085  * DOM Rangeが使える環境(Firefox2+,Opera9+,Safari3+)なら、innerHTMLいらずで、ガーって書けます。\r
1086  * return document.createRange().createContextualFragment("<div><select><option></option></select></div>");\r
1087  * insertAdjacentHTML\r
1088  * \r
1089  * ie7 以下では iframe の frameborder や、input name は、createElement 後に setAttribute しても無視される\r
1090  * \r
1091  * fragument がある場合 children も足して\r
1092  * Mozilla: 1.0+, IE: 5.5+, Netscape: 2.0+, Safari: 1.0+, Opera: 7.0+\r
1093  * ie6 大丈夫?fragment の場合リークしないか?チェックが必要\r
1094  * http://msdn.microsoft.com/ja-jp/library/bb250448%28v=vs.85%29.aspx\r
1095  * \r
1096  * document.createElement of ie4 is only for OPTION & IMAGE.\r
1097  */\r
1098 Node.prototype._actualCreate =\r
1099         X.Dom.DOM_W3C ? (function( isChild ){\r
1100                 var elm = this._rawNode,\r
1101                         xnodes, frg, i, l;\r
1102                 \r
1103                 if( this._xnodeType === 3 ){\r
1104                         if( elm ) return elm;\r
1105                         delete this._dirty;\r
1106                         return this._rawNode = document.createTextNode( X.Dom.chrReferanceTo( this._text ) );\r
1107                 };\r
1108                 \r
1109                 if( !elm ){\r
1110                         if( this._dirty & X.Dom.Dirty.CSS && !( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
1111                                 delete this._cssText;\r
1112                         };\r
1113                         this._isNew = true;\r
1114                         this._rawNode = elm =\r
1115                                 X.Dom._strictElmCreation ?\r
1116                                         document.createElement( [\r
1117                                                 '<', this._tag,\r
1118                                                         ' UID="', this._uid, '"',\r
1119                                                         this._id ? ' id="' + this._id + '"' : '',\r
1120                                                         this._className ? ' class="' + this._className + '"' : '',\r
1121                                                         this._attrText === false ? ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ) : this._attrText,\r
1122                                                         this._cssText ? ' style="' + this._cssText + '"' : '',\r
1123                                                 '>' ].join( '' ) ) :\r
1124                                         document.createElement( this._tag );\r
1125                 };\r
1126                 if( X.Dom._useDocumentFragment ){\r
1127                         if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
1128                                 !isChild && ( frg = X.Dom._useDocumentFragment ).appendChild( elm );\r
1129                                 for( i = 0; i < l; ++i ){\r
1130                                         elm.appendChild( xnodes[ i ]._actualCreate( true ) );\r
1131                                 };\r
1132                                 return frg || elm;\r
1133                         };\r
1134                 };\r
1135                 \r
1136                 return elm;\r
1137         }) :\r
1138         X.Dom.DOM_IE4 ? (function( isChild ){\r
1139                 var uid = this._uid,\r
1140                         html, xnodes, n, i, l;\r
1141                 \r
1142                 if( this._xnodeType === 3 ){\r
1143                         html = [ '<FONT id=ie4uid', uid, ' UID="', uid, '">', this._text, '</FONT>' ];// fake textNode\r
1144                         delete this._rawNode;\r
1145                 } else {\r
1146                         if( this._rawNode && !isChild ) this._actualRemove( true );\r
1147                         \r
1148                         if( this._dirty & X.Dom.Dirty.CSS && !( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
1149                                 delete this._cssText;\r
1150                         };\r
1151                         \r
1152                         html = [\r
1153                                 '<', this._tag, ' id=', ( this._id || ( 'ie4uid' + uid ) ), ' UID="', uid, '"',\r
1154                                 this._className ? ' class="' + this._className + '"' : '',\r
1155                                 this._attrText === false ? ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ) : this._attrText,\r
1156                                 this._cssText ? ' style="' + this._cssText + '"' : '',\r
1157                         '>' ];\r
1158                         \r
1159                         n = html.length;\r
1160                         if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
1161                                 if( l === 1 && xnodes[ 0 ]._xnodeType === 3 ){\r
1162                                         // only textnode\r
1163                                         html[ n ] = xnodes[ 0 ]._text;\r
1164                                         ++n;\r
1165                                         this._state |= X.Dom.State.IE4_ONLY_TEXT;\r
1166                                 } else {\r
1167                                         for( i = 0; i < l; ++i ){\r
1168                                                 html[ n ] = xnodes[ i ]._actualCreate( true );\r
1169                                                 ++n;\r
1170                                         };                                      \r
1171                                 };\r
1172                         };\r
1173                         X.Dom.DTD.EMPTY[ this._tag ] || ( html[ n ] = '<\/' + this._tag + '>' );\r
1174                         \r
1175                         delete this._newAttrs;\r
1176                 };\r
1177                 \r
1178                 return html.join( '' );\r
1179         }) :\r
1180         (function(){});\r
1181 \r
1182 Node.prototype._afterActualCreate =\r
1183         X.Dom.DOM_W3C ? (function(){\r
1184                 var elm = this._rawNode, xnodes, l, attrs, k, i;\r
1185 \r
1186                 this._root  = this.parent._root;\r
1187                 \r
1188                 if( this._xnodeType === 3 ){\r
1189                         this._dirty && this._updateRawNode( elm );\r
1190                         return this;\r
1191                 };\r
1192                         \r
1193                 xnodes = this._xnodes;\r
1194                 l      = xnodes && xnodes.length;\r
1195                 \r
1196                 if( this._isNew ){\r
1197                         if( !X.Dom._useDocumentFragment && l ){// docFrg が使えない場合、doc 追加後に子を追加\r
1198                                 for( i = 0; i < l; ++i ){\r
1199                                         elm.appendChild( xnodes[ i ]._actualCreate( true ) );\r
1200                                 };\r
1201                         };\r
1202                         if( !X.Dom._strictElmCreation ){\r
1203                                 elm.UID = this._uid;\r
1204                                 this._newAttrs = this._attrs;\r
1205                                 this._dirty = X.Dom.Dirty.ID | X.Dom.Dirty.CLASSNAME | X.Dom.Dirty.CSS | X.Dom.Dirty.ATTR | X.Dom.Dirty.IE_FILTER;\r
1206                                 this._updateRawNode( elm );\r
1207                         } else\r
1208                         if( this._dirty & X.Dom.Dirty.IE_FILTER ){\r
1209                                 elm.style.filter = X.Dom.Style.SPECIAL_FIX( this._css );\r
1210                                 delete this._dirty;\r
1211                         };\r
1212                         \r
1213                         delete this._isNew;\r
1214                 } else {\r
1215                         this._dirty && this._updateRawNode( elm );\r
1216                 };\r
1217                 \r
1218                 if( l ){\r
1219                         for( i = 0; i < l; ++i ){\r
1220                                 xnodes[ i ]._afterActualCreate();\r
1221                         };\r
1222                 };\r
1223                 // src の onload があるので先ではないか?\r
1224                 // ie の str から要素を作る場合、srcだけ イベント設定後ではないか?\r
1225                 this._restoreEvent();// イベントの復帰\r
1226         }) :\r
1227         X.Dom.DOM_IE4 ? (function(){\r
1228                 var xnodes, i;\r
1229                 this._root = this.parent._root;\r
1230                 \r
1231                 if( this._xnodeType !== 1 ) return this;\r
1232                 \r
1233                 if( ( xnodes = this._xnodes ) && ( i = xnodes.length ) ){\r
1234                         for( ; i; ){\r
1235                                 xnodes[ --i ]._afterActualCreate();\r
1236                         };\r
1237                 };\r
1238                 // textarea への value の適用はここで\r
1239                 if( this._dirty & X.Dom.Dirty.IE_FILTER ){\r
1240                         this._ie4getRawNode().style.filter = X.Dom.Style.SPECIAL_FIX( this._css );\r
1241                 };\r
1242                 delete this._dirty;\r
1243                 this._restoreEvent();// イベントの復帰\r
1244         }) :\r
1245         (function(){});\r
1246 \r
1247 Node.prototype._actualRemove =\r
1248         X.Dom.DOM_W3C ?\r
1249                 ( function( isChild ){\r
1250                         var xnodes = this._xnodes,\r
1251                                 elm    = this._rawNode,\r
1252                                 child, i, l;\r
1253                         if( xnodes && ( l = xnodes.length ) ){\r
1254                                 for( i = 0; i < l; ++i ){\r
1255                                         child = xnodes[ i ];\r
1256                                         child._xnodeType === 1 && child._actualRemove( true );\r
1257                                 };\r
1258                         };\r
1259 \r
1260                         if( !elm ) return;\r
1261                         this._xnodeType === 1 && this._migrateEvent();// イベントの退避\r
1262                         // elm.parentNode.tagName for ie7\r
1263                         if( !X.UA.MacIE ){\r
1264                                 !isChild && elm.parentNode && elm.parentNode.tagName && elm.parentNode.removeChild( elm );\r
1265                         } else {\r
1266                                 !isChild && elm.parentNode && elm.parentNode.tagName && X.Dom._fixed_remove( elm, this );\r
1267                         };\r
1268                 }) :\r
1269         X.Dom.DOM_IE4 ?\r
1270                 ( function( isChild ){\r
1271                         var xnodes = this._xnodes,\r
1272                                 elm    = this._rawNode || this._ie4getRawNode(),\r
1273                                 i, l, xnode;\r
1274                         if( xnodes && ( l = xnodes.length ) ){\r
1275                                 for( i = 0; i < l; ++i ){\r
1276                                         xnodes[ i ]._actualRemove( true );\r
1277                                 };\r
1278                         };\r
1279 \r
1280                         if( !elm ) return;\r
1281                         this._xnodeType === 1 && this._migrateEvent();// イベントの退避\r
1282                         \r
1283                         if( X.Dom.Attr.HAS_VALUE[ this._tag ] && ( !this._newAttrs || !X.inObject( 'value', this._newAttrs ) ) ){\r
1284                                 this._attrs.value = elm.value;\r
1285                         };\r
1286                         elm.removeAttribute( 'id' ); // ?\r
1287                         document.all[ this._id || ( 'ie4uid' + this._uid ) ] = null; // MacIE5 でエラー\r
1288                         if( !isChild ) elm.outerHTML = '';\r
1289                         delete this._rawNode;\r
1290                 }) :\r
1291                 (function(){});\r
1292 \r
1293 console.log( 'X.Dom.Node' );\r
1294 \r