OSDN Git Service

cbfcdf69b8f5415707e2de9b9cf03f8021b7f23d
[pettanr/clientJs.git] / 0.6.x / js / 02_dom / 02_XNode.js
1 var \r
2         \r
3         X_Node_State = {\r
4                 DESTROYED              : 0x0,\r
5                 EXIST                  : 0x1,\r
6                 IN_TREE                : 0x2, // xnode が(仮想)ツリーに追加されている -> 描画の対象\r
7                 \r
8                 STYLE_IS_DISPLAY_NONE  : 2 <<  1, // display    : none          \r
9                 STYLE_IS_INVISIBLE     : 2 <<  2, // visibility : hidden or opacity : 0\r
10                 STYLE_IS_POS_ABSOLUTE  : 2 <<  3, // position   : absolute\r
11                 STYLE_IS_NO_OVERFLOW   : 2 <<  4, // overflow   : hidden\r
12                 STYLE_IS_WIDTH_LENGTH  : 2 <<  5, // width  : overflow:hidden,要素無し、または要素が非表示なら、 width() のための commitUpdate が不要\r
13                 STYLE_IS_WIDTH_PCT     : 2 <<  6, // width  : width() のための commitUpdate が不要かもしれない。(親で LENGTH が指定されているなら)\r
14                 STYLE_IS_HEIGHT_LENGTH : 2 <<  7, // height :\r
15                 STYLE_IS_HEIGHT_PCT    : 2 <<  8, // height :\r
16                 STYLE_IS_FONT_LENGTH   : 2 <<  9, // fontSize :\r
17                 STYLE_IS_FONT_PCT      : 2 << 10, // fontSize :\r
18 \r
19                 DIRTY_POSITION         : 2 << 11, // 要素位置の変更が起こった。\r
20                 DIRTY_CONTENT          : 2 << 12, // width, height, x, y textNode の内容 TODO html と排他なので ID と共通でいい\r
21                 DIRTY_ID               : 2 << 12, // width, height, x, y\r
22                 DIRTY_CLASSNAME        : 2 << 13, // X_Node_CSS_getCharSize, width, height, x, y\r
23                 DIRTY_ATTR             : 2 << 14, // X_Node_CSS_getCharSize, width, height, x, y\r
24                 DIRTY_CSS              : 2 << 15, // X_Node_CSS_getCharSize, width, height, x, y\r
25                 DIRTY_IE_FILTER        : X_UA.IE < 10 && X_UA.ActiveX ? 2 << 16 : 0, // \r
26 \r
27                 ACTUAL_LISTENING       : 2 << 17,\r
28                 OLD_ATTRTEXT           : 2 << 18,\r
29                 OLD_CSSTEXT            : 2 << 19,\r
30 \r
31                 // filter 要素が親子になると不具合が出るのを検出\r
32                 IE_FILTER_NOW          : 2 << 20,\r
33 \r
34                 //GPU_WAITING            : 2 << 20, // 1:子のGPU解除待\r
35                 GPU_RESERVED           : 2 << 21, // 2:GPU予約\r
36                 GPU_NOW                : 2 << 22, // 3:GPU now!\r
37                 GPU_RELEASE_RESERVED   : 2 << 23, // 4:GPU解除予約\r
38                 \r
39                 IE4_HAS_TEXTNODE       : X_UA.IE4 ? 2 << 21 : 0,\r
40                 IE4_HAS_ELEMENT        : X_UA.IE4 ? 2 << 22 : 0,\r
41                 IE4_DIRTY_CHILDREN     : X_UA.IE4 ? 2 << 23 : 0,\r
42                 IE4_FIXED              : X_UA.IE4 ? 2 << 24 : 0,\r
43                 \r
44                 IE5_DISPLAY_NONE_FIX   : X_UA.IE5 && X_UA.ActiveX ? 2 << 24 : 0\r
45         },\r
46 \r
47         X_Node_BITMASK_RESET_STYLE  = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ (\r
48                 X_Node_State.STYLE_IS_DISPLAY_NONE |\r
49                 X_Node_State.STYLE_IS_INVISIBLE |\r
50                 X_Node_State.STYLE_IS_POS_ABSOLUTE |\r
51                 X_Node_State.STYLE_IS_NO_OVERFLOW |\r
52                 X_Node_State.STYLE_IS_WIDTH_LENGTH |\r
53                 X_Node_State.STYLE_IS_WIDTH_PCT |\r
54                 X_Node_State.STYLE_IS_HEIGHT_LENGTH |\r
55                 X_Node_State.STYLE_IS_HEIGHT_PCT |\r
56                 X_Node_State.STYLE_IS_FONT_LENGTH |\r
57                 X_Node_State.STYLE_IS_FONT_PCT ),\r
58 \r
59         X_Node_BitMask_IS_DIRTY     = X_Node_State.DIRTY_POSITION | \r
60                 X_Node_State.DIRTY_CONTENT | X_Node_State.DIRTY_ID | X_Node_State.DIRTY_CLASSNAME |\r
61                 X_Node_State.DIRTY_ATTR | X_Node_State.DIRTY_CSS | X_Node_State.DIRTY_IE_FILTER,\r
62 \r
63         X_Node_BitMask_RESET_DIRTY  = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ X_Node_BitMask_IS_DIRTY,\r
64         \r
65         X_Node_BitMask_RESET_GPU    = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ ( X_Node_State.GPU_RESERVED | X_Node_State.GPU_NOW | X_Node_State.GPU_RELEASE_RESERVED ),\r
66         \r
67         X_Node_BitMask_IE4_IS_MIX   = X_Node_State.IE4_HAS_TEXTNODE | X_Node_State.IE4_HAS_ELEMENT,\r
68         \r
69         X_Node_TYPE = {\r
70                 XNODE       : 1,\r
71                 RAW_HTML    : 2,\r
72                 RAW_TEXT    : 3,\r
73                 HTML_STRING : 4,\r
74                 STRING      : 5,\r
75                 //DOC_FRAG    : 6,\r
76                 XNODE_LIST  : 7,\r
77                 WINDOW      : 8,\r
78                 DOCUMENT    : 9,\r
79                 IMAGE       : 10\r
80         },\r
81         \r
82         X_Node_strictElmCreation    = !X_UA.MacIE && X_UA.IE5678,// && !X_UA.MacIE;\r
83         \r
84         X_Node_documentFragment     = document.createDocumentFragment && ( !X_UA.IE || 5.5 <= X_UA.IE ) && document.createDocumentFragment(),\r
85         \r
86         // 子の生成後に リアル文書 tree に追加する\r
87         X_Node_addTreeAfterChildren = !( X.UA.IE < 9 ),\r
88         \r
89         X_Node_displayNoneFixForIE5 = !!X_Node_State.IE5_DISPLAY_NONE_FIX,\r
90         \r
91         X_Node_newByTag      = false,\r
92         \r
93         X_Node_newByText     = false,\r
94         \r
95         X_Node_outerXNode    = null,\r
96         \r
97         X_Node_updateTimerID = 0,\r
98 /*\r
99  * Node( rawElement | rawTextnode | htmlString | textString )\r
100  */     \r
101         Node = X.Node = X.EventDispatcher.inherits(\r
102         'XDomNode',\r
103         X.Class.POOL_OBJECT, // X.Class.FINAL\r
104         {\r
105                 _uid       : 0,\r
106                 _flags     : X_Node_State.DESTROYED,\r
107 \r
108                 // _rawObject : null,\r
109                 _rect      : null, // \r
110                 _fontSize  : 0,\r
111                 \r
112                 length     : 1,\r
113                 parent     : null, // remove された枝も親子構造は維持している。\r
114                 _xnodes    : null, // Array.<Node>\r
115 \r
116                 _tag       : '',\r
117                 _text      : '',\r
118                 _id        : '', //\r
119                 _className : '', //\r
120 \r
121                 _attrs     : null, // see X_Node_Attr\r
122                 _newAttrs  : null,\r
123                 _attrText  : '',\r
124                 \r
125                 _css       : null, // see X_Node_CSS\r
126                 _cssText   : '',\r
127                 \r
128                 _anime     : null, // Hash see X_Node_Anime\r
129                 \r
130         /*\r
131          * TODO Node の継承ができない!\r
132          */\r
133                 Constructor : function( v ){\r
134                         var uid = X_Node_CHASHE.length,\r
135                                 css, xnodes, xnode, parent;\r
136                         \r
137                         if( X_Node_newByTag ){\r
138                                 X_Node_newByTag = false;\r
139                                 this._tag       = v.toUpperCase();\r
140                                 arguments[ 1 ] && this.attr( arguments[ 1 ] );\r
141                                 css = arguments[ 2 ];\r
142                                 css && this[ X.Type.isString( css ) ? 'cssText' : 'css' ]( css );\r
143                         } else\r
144                         if( X_Node_newByText ){\r
145                                 X_Node_newByText = false;\r
146                                 this._text       = v;\r
147                         } else {\r
148                                 if( 1 < arguments.length ) return new X_NodeList( arguments );\r
149                                 if( X.Type.isArray( v ) && v.length ) return new X_NodeList( v );\r
150 \r
151                                 switch( X_Node_getType( v ) ){\r
152                                         case X_Node_TYPE.XNODE :\r
153                                         case X_Node_TYPE.XNODE_LIST :\r
154                                                 return v;\r
155 \r
156                                         case X_Node_TYPE.RAW_HTML :\r
157                                                 if( xnode = X_Node_getXNode( v ) ) return xnode;\r
158                                                 // v.parentNode || v.parentElement : dom1 || dom0\r
159                                                 this.parent     = ( parent = v.parentNode || v.parentElement ) && parent.tagName /* ie7- */ && X_Node_getXNode( parent );\r
160                                                 this._rawObject = v;\r
161                                                 this._tag       = v.tagName.toUpperCase();\r
162                                                 this._id        = v.id;\r
163                                                 this._className = v.className;\r
164                                                 \r
165                                                 this.cssText( v.style.cssText );\r
166                                                 this._flags &= X_Node_BitMask_RESET_DIRTY; // X_Node_State.DIRTY_CSS を落とす\r
167                                                 \r
168                                                 // TODO attr の回収は不可能、、、?\r
169                                                 if( X_UA_DOM.IE4 ){\r
170                                                         v.setAttribute( 'UID', '' + uid );\r
171                                                 } else {\r
172                                                         v.UID = uid;\r
173                                                 };\r
174                                                 // childNodes...\r
175                                                 break;\r
176 \r
177                                         case X_Node_TYPE.RAW_TEXT :\r
178                                                 if( xnode = X_Node_getXNode( v ) ) return xnode;\r
179                                                 this.parent     = X_Node_getXNode( v.parentNode );\r
180                                                 this._rawObject = v;\r
181                                                 this._text      = v.data;\r
182                                                 v.UID = uid;\r
183                                                 break;\r
184 \r
185                                         case X_Node_TYPE.HTML_STRING :\r
186                                         case X_Node_TYPE.STRING :\r
187                                                 if( xnodes = X_HtmlParser_parse( v, true ) && 1 < xnodes.length ) return new X_NodeList( xnodes );\r
188                                                 if( xnodes.length ) return xnodes[ 0 ];\r
189                                                 return X_Node_none;\r
190 \r
191                                         default :\r
192                                                 this.length = 0;\r
193                                                 if( X_Node_none ) return X_Node_none;\r
194                                                 return;\r
195                                 };\r
196                         };\r
197                         \r
198                         if( this.parent && ( this.parent._flags & X_Node_State.IN_TREE ) ){\r
199                                 this._flags |= X_Node_State.IN_TREE;\r
200                         };\r
201                         this._flags |= X_Node_State.EXIST;\r
202                         X_Node_CHASHE[ this._uid = uid ] = this;\r
203                 },\r
204                 \r
205                 // attr\r
206                 // css, cssText\r
207                 // find\r
208                 // animate, stop\r
209                 \r
210                 create         : X_Node_create,\r
211                 \r
212                 createAt       : X_Node_createAt,\r
213                 \r
214                 createText     : X_Node_createText,\r
215                 \r
216                 createTextAt   : X_Node_createTextAt,\r
217                 \r
218                 clone          : X_Node_clone,\r
219                 \r
220                 append         : X_Node_append,\r
221                 \r
222                 appendAt       : X_Node_appendAt,\r
223                 \r
224                 appendTo       : X_Node_appendTo,\r
225                 \r
226                 appendToRoot   : X_Node_appendToRoot, // remove\r
227                 \r
228                 before         : X_Node_before, // remove\r
229                 \r
230                 prev           : X_Node_before,\r
231                 \r
232                 after          : X_Node_after, // remove\r
233                 \r
234                 next           : X_Node_after,\r
235                 \r
236                 swap           : X_Node_swap,\r
237                 \r
238                 remove         : X_Node_remove,\r
239                 \r
240                 empty          : X_Node_empty,\r
241                 \r
242                 destroy        : X_Node_destroy, // -> kill && kill event\r
243                 \r
244                 contains       : X_Node_contains,\r
245                 \r
246                 getChildAt     : X_Node_getChildAt,\r
247                 \r
248                 numChildren    : X_Node_length,\r
249                 \r
250                 firstChild     : X_Node_firstChild,\r
251                 \r
252                 lastChild      : X_Node_lastChild,\r
253                 \r
254                 getOrder       : X_Node_getOrder,\r
255                 \r
256                 className      : X_Node_className,\r
257                 addClass       : X_Node_addClass,\r
258                 removeClass    : X_Node_removeClass,\r
259                 toggleClass    : X_Node_toggleClass,\r
260                 hasClass       : X_Node_hasClass,\r
261                 \r
262                 html           : X_Node_html,\r
263                 text           : X_Node_text,\r
264                 call           : X_Node_call,\r
265                 each           : X_Node_each\r
266                 \r
267         }\r
268 );\r
269 \r
270 function X_Node_getType( v ){\r
271         if( v === '' ) return X_Node_TYPE.STRING;\r
272         if( !v ) return 0;\r
273         if( v === window ) return X_Node_TYPE.WINDOW;\r
274         if( v === document ) return X_Node_TYPE.DOCUMENT;\r
275         if( v.constructor === Node ) return X_Node_TYPE.XNODE;\r
276         if( v.constructor === X_NodeList ) return X_Node_TYPE.XNODE_LIST;\r
277         if( X.Type.isHTMLElement( v ) ) return X_Node_TYPE.RAW_HTML;\r
278         if( v.nodeType === 3 ) return X_Node_TYPE.RAW_TEXT;\r
279         if( X.Type.isString( v ) ){\r
280                 return '<' === v.charAt( 0 ) && v.charAt( v.length - 1 ) === '>' ? X_Node_TYPE.HTML_STRING : X_Node_TYPE.STRING;\r
281         };\r
282         return 0;\r
283 };\r
284 function X_Node_getXNode( v ){\r
285         var uid, i, chashe, xnode;\r
286         switch( X_Node_getType( v ) ){\r
287                 case X_Node_TYPE.XNODE :\r
288                 case X_Node_TYPE.XNODE_LIST :\r
289                         return v;\r
290                 case X_Node_TYPE.RAW_HTML :\r
291                         // fake TextNode too.\r
292                         if( X_UA_DOM.IE4 ){\r
293                                 uid = v.getAttribute( 'UID' );\r
294                                 return uid && X_Node_CHASHE[ uid ];\r
295                         };\r
296                         return v.UID && X_Node_CHASHE[ v.UID ];\r
297                 case X_Node_TYPE.WINDOW :\r
298                         return X_ViewPort;\r
299                 case X_Node_TYPE.DOCUMENT :\r
300                         return X_ViewPort_document;\r
301                 case X_Node_TYPE.RAW_TEXT :\r
302                         if( v.UID ) return X_Node_CHASHE[ v.UID ];\r
303                         for( chashe = X_Node_CHASHE, i = chashe.length; i; ){\r
304                                 if( ( xnode = X_Node_CHASHE[ --i ] ) && ( xnode._rawObject === v ) ) return xnode;\r
305                         };\r
306         };\r
307 };\r
308 \r
309 function X_Node_getRoot( xnode ){\r
310         return X_ViewPort_document;\r
311         //return X_Node_body._rawObject.documentElement ? node : node.ownerDocument || node.document;\r
312 };\r
313         // XMLかどうかを判別する\r
314 var X_Node_isXmlDocument =\r
315                 X_UA_DOM.IE4 ?\r
316                         X.emptyFunction :\r
317                         (function( root ){\r
318                                 if( X.Type.isBoolean( root.isXML ) ) return root.isXML;\r
319                                 return root.isXML = root._rawObject.createElement( 'p' ).tagName !== root._rawObject.createElement( 'P' ).tagName;\r
320                         }),\r
321         X_Node_CHASHE     = [],\r
322         X_Node_none  = X_Node_CHASHE[ 0 ] = new Node(),\r
323         X_Node_html, // = X_Node_CHASHE[ 1 ] <html>\r
324         X_Node_head, // = X_Node_CHASHE[ 2 ] <head>\r
325         X_Node_body, // = X_Node_CHASHE[ 3 ] <body>\r
326         X_Node_systemNode, // = X_Node_CHASHE[ ? ]\r
327         X_Node_fontSizeNode,\r
328 /*\r
329  * remove :\r
330  *  X_Node_reserveRemoval = [] に追加。commitUpdate で remove\r
331  * add :\r
332  *  X_Node_reserveRemoval にいたら消す, new_parent._xnodes に挿入\r
333  */\r
334         X_Node_reserveRemoval = [];\r
335 \r
336 \r
337 var X_Node__ie4getRawNode = X_UA_DOM.IE4 && function ( that ){\r
338                 return that._rawObject ||\r
339                         ( that._rawObject = document.all[ 'ie4uid' + that._uid ] ) ||\r
340                         ( that._id && ( that._rawObject = document.all[ that._id ] ) );\r
341         };\r
342 \r
343 \r
344 function X_Node_toggleInTreeFlag( xnodes, flag ){\r
345         var i = xnodes.length, xnode;\r
346         for( ; i; ){\r
347                 xnode = xnodes[ --i ];\r
348                 flag ? ( xnode._flags |= X_Node_State.IN_TREE | X_Node_State.DIRTY_POSITION ) : ( xnode._flags &= ~X_Node_State.IN_TREE & ~X_Node_State.IE5_DISPLAY_NONE_FIX );\r
349                 xnode._xnodes && X_Node_toggleInTreeFlag( xnode._xnodes, flag );\r
350         };\r
351 };\r
352 \r
353 /* --------------------------------------\r
354  *  Create\r
355  */\r
356 function X_Node_create( tag, opt_attrs, opt_css ){\r
357         var xnode;\r
358         if( !this._tag ) return;\r
359         this.append( xnode = X_Doc_create( tag, opt_attrs, opt_css ) );\r
360         return xnode;\r
361 };\r
362 function X_Node_createAt( index, tag, opt_attrs, opt_css ){\r
363         var xnode;\r
364         if( !this._tag ) return;\r
365         this.appendAt( index, xnode = X_Doc_create( tag, opt_attrs, opt_css ) );\r
366         return xnode;\r
367 };\r
368 \r
369 /* --------------------------------------\r
370  *  CreateText\r
371  */\r
372 function X_Node_createText( text ){\r
373         var xnode;\r
374         if( !this._tag ) return;\r
375         this.append( xnode = X_Doc_createText( text ) );\r
376         return xnode;\r
377 };\r
378 function X_Node_createTextAt( index, text ){\r
379         var xnode;\r
380         if( !this._tag ) return;\r
381         this.appendAt( index, xnode = X_Doc_createText( text ) );\r
382         return xnode;\r
383 };\r
384 \r
385 /* --------------------------------------\r
386  *  Clone\r
387  * http://d.hatena.ne.jp/think49/20110724/1311472811\r
388  * http://d.hatena.ne.jp/uupaa/20100508/1273299874\r
389  */\r
390 function X_Node_clone( opt_clone_children ){\r
391         var xnode, xnodes, i, l;\r
392         if( this._tag ){\r
393                 X_Node_newByTag = true;\r
394                 xnode = new Node( this._tag, X_Object_clone( this._attrs ), X_Object_clone( this._css ) )\r
395                         .attr( { 'id' : this._id } )\r
396                         .className( this._className );\r
397                 if( opt_clone_children && ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
398                         for( i = 0; i < l; ++i ){\r
399                                 xnode.append( xnodes[ i ].clone( true ) );\r
400                         };\r
401                 };\r
402                 return xnode;           \r
403         };\r
404         X_Node_newByText = true;\r
405         return new Node( this._text );\r
406 };\r
407 \r
408 /* --------------------------------------\r
409  *  Add\r
410  * Node\r
411  * HtmlElement の場合は内部使用専用 そのため event の破棄等しない\r
412  */\r
413 function X_Node_append( v ){\r
414         var i, l, xnodes, frg;\r
415         if( !this._tag ) return;\r
416         \r
417         if( 1 < ( l = arguments.length ) ){\r
418                 for( i = 0; i < l; ++i ){\r
419                         this.append( arguments[ i ] );\r
420                 };\r
421                 return this;\r
422         };\r
423         \r
424         if( !( xnodes = this._xnodes ) ) this._xnodes = xnodes = [];\r
425         \r
426         switch( X_Node_getType( v ) ){\r
427                 case X_Node_TYPE.RAW_HTML :\r
428                 case X_Node_TYPE.RAW_TEXT :\r
429                         v = new Node( v );\r
430                         break;\r
431                 case X_Node_TYPE.HTML_STRING :\r
432                 case X_Node_TYPE.STRING :\r
433                         return this.append.apply( this, X_HtmlParser_parse( v, true ) );\r
434                 case X_Node_TYPE.XNODE :\r
435                         // 親の xnodes から v を消す\r
436                         v.parent && v.remove();\r
437                         // IE4 でテキストノードの追加、FIXED 済でない場合、親に要素の追加を通知\r
438                         if( X_UA.IE4 && !v._tag && ( this._flags & X_Node_State.IE4_FIXED ) === 0 ) this._flags |= X_Node_State.IE4_DIRTY_CHILDREN;\r
439                         break;\r
440                 default :\r
441                         return this;\r
442         };\r
443 \r
444         v.parent = this;\r
445         xnodes[ xnodes.length ] = v;\r
446         if( this._flags & X_Node_State.IN_TREE ){\r
447                 v._flags |= X_Node_State.IN_TREE;\r
448                 v._xnodes && X_Node_toggleInTreeFlag( v._xnodes, true );\r
449                 X_Node_reserveUpdate();\r
450         };\r
451         return this;\r
452 };\r
453 \r
454 \r
455 function X_Node_appendAt( start, v ){\r
456         var xnodes, l, i;\r
457         \r
458         if( !this._tag ) return this;\r
459         \r
460         l = arguments.length;\r
461         if( !( xnodes = this._xnodes ) ) xnodes = this._xnodes = [];\r
462         \r
463         if( xnodes.length <= start ){\r
464                 if( l === 2 ) return this.append( v );\r
465                 for( i = 1; i < l; ++i ){\r
466                         this.append( arguments[ i ] );\r
467                 };\r
468                 return this;\r
469         };\r
470         if( start < 0 ) start = 0;\r
471         if( 2 < l ){\r
472                 for( ; l; ){\r
473                         this.appendAt( start, arguments[ --l ] );\r
474                 };\r
475                 return this;\r
476         };\r
477 \r
478         switch( X_Node_getType( v ) ){\r
479                 case X_Node_TYPE.RAW_HTML :\r
480                 case X_Node_TYPE.RAW_TEXT :\r
481                         v = new Node( v );\r
482                         break;\r
483                 case X_Node_TYPE.HTML_STRING :\r
484                 case X_Node_TYPE.STRING :\r
485                         v = X_HtmlParser_parse( v, true );\r
486                         for( i = v.length; i; ){\r
487                                 this.appendAt( start, v[ --i ] );\r
488                         };\r
489                         return this;\r
490                 case X_Node_TYPE.XNODE :\r
491                         // 親の xnodes から v を消す\r
492                         v.parent && v.remove();\r
493                         // IE4 でテキストノードの追加、FIXED 済でない場合、親に要素の追加を通知\r
494                         if( X_UA.IE4 && !v._tag && ( this._flags & X_Node_State.IE4_FIXED ) === 0 ) this._flags |= X_Node_State.IE4_DIRTY_CHILDREN;\r
495                         break;\r
496                 default :\r
497                         return this;\r
498         };\r
499 \r
500         v.parent = this;\r
501         this._xnodes.splice( start, 0, v );\r
502         if( this._flags & X_Node_State.IN_TREE ){\r
503                 v._flags |= X_Node_State.IN_TREE;\r
504                 v._xnodes && X_Node_toggleInTreeFlag( v._xnodes, true );\r
505                 X_Node_reserveUpdate();\r
506         };\r
507         return this;\r
508 };\r
509 \r
510 function X_Node_appendTo( parent, opt_index ){\r
511         switch( X_Node_getType( parent ) ){\r
512                 case X_Node_TYPE.RAW_HTML :\r
513                         parent = new Node( parent );\r
514                         break;\r
515                 case X_Node_TYPE.HTML_STRING :\r
516                         parent = X_HtmlParser_parse( parent, true );\r
517                         parent = parent[ 0 ] || parent;\r
518                 case X_Node_TYPE.XNODE :\r
519                         break;\r
520                 default :\r
521                         return this;\r
522         };\r
523         opt_index === undefined ? parent.append( this ) : parent.appendAt( opt_index, this );\r
524         return this;\r
525 };\r
526 \r
527 function X_Node_appendToRoot( opt_index ){\r
528         opt_index === undefined ? X_Node_body.append( this ) : X_Node_body.appendAt( opt_index, this );\r
529         return this;\r
530 };\r
531 \r
532 /* --------------------------------------\r
533  *  Before , After, Replace\r
534  */\r
535 function X_Node_before( v ){\r
536         var parent = this.parent, xnodes, i, l, start;\r
537         \r
538         // getter\r
539         if( v === undefined ){\r
540                 if( !parent ) return;\r
541                 xnodes = parent._xnodes;\r
542                 i      = xnodes.indexOf( this );\r
543                 return 0 < i ? xnodes[ i - 1 ] : v;\r
544         };\r
545         \r
546         if( !parent ) return this;\r
547         \r
548         l = arguments.length;\r
549         start = this.getOrder();\r
550         if( 1 < l ){\r
551                 for( ; l; ){\r
552                         parent.appendAt( start, arguments[ --l ] );\r
553                 };\r
554                 return this;\r
555         };\r
556         parent.appendAt( start, v );\r
557         return this;\r
558 };\r
559 \r
560 function X_Node_after( v ){\r
561         var parent = this.parent, xnodes, i, l, start;\r
562         \r
563         // getter\r
564         if( v === undefined ){\r
565                 if( !parent ) return;\r
566                 xnodes = parent._xnodes;\r
567                 i      = xnodes.indexOf( this );\r
568                 return ++i < xnodes.length ? xnodes[ i ] : v;\r
569         };\r
570         \r
571         if( !parent ) return this;\r
572         \r
573         l = arguments.length;\r
574         start = this.getOrder() + 1;\r
575         if( parent._xnodes.length <= start ){\r
576                 if( 1 < l ){\r
577                         for( i = 0; i < l; ++i ){\r
578                                 parent.append( arguments[ i ] );\r
579                         };\r
580                         return this;\r
581                 };\r
582                 parent.append( v );\r
583                 return this;\r
584         };\r
585         if( 1 < l ){\r
586                 for( ; l; ){\r
587                         parent.appendAt( start, arguments[ --l ] );\r
588                 };\r
589                 return this;\r
590         };\r
591         parent.appendAt( start, v );\r
592         return this;\r
593 };\r
594 \r
595 function X_Node_swap( v ){\r
596         if( !this.parent ) return this;\r
597         return arguments.length === 1 ? this.before( v ).remove() : this.before.apply( this, arguments ).remove();\r
598 };\r
599 \r
600 /* --------------------------------------\r
601  *  Remove\r
602  */\r
603 function X_Node_remove(){\r
604         var parent = this.parent,\r
605                 elm;\r
606         \r
607         if( !parent ) return this;\r
608 \r
609         delete this.parent;\r
610         parent._xnodes.splice( parent._xnodes.indexOf( this ), 1 );\r
611         \r
612         if( this._flags & X_Node_State.IN_TREE ){\r
613                 this._flags &= ~X_Node_State.IN_TREE & ~X_Node_State.IE5_DISPLAY_NONE_FIX;\r
614                 this._xnodes && X_Node_toggleInTreeFlag( this._xnodes, false );\r
615 \r
616                 if( X_UA_DOM.IE4 ){\r
617                         elm = this._rawObject || X_Node__ie4getRawNode( this );\r
618                         if( elm ){\r
619                                 X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = this;\r
620                                 X_Node_reserveUpdate();                 \r
621                         } else\r
622                         if( !this._tag && ( parent._flags & X_Node_State.IE4_FIXED ) === 0 ){\r
623                                 parent._flags |= X_Node_State.IE4_DIRTY_CHILDREN;\r
624                         };\r
625                 } else {\r
626                         elm = this._rawObject;\r
627                         if( elm && elm.parentNode && elm.parentNode.tagName ){\r
628                                 X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = this;\r
629                                 X_Node_reserveUpdate();                 \r
630                         };\r
631                 };\r
632         };\r
633         return this;\r
634 };\r
635 \r
636 function X_Node_empty(){\r
637         var xnodes = this._xnodes, i;\r
638         if( xnodes && ( i = xnodes.length ) ){\r
639                 for( ; i; ){\r
640                         xnodes[ --i ].destroy();\r
641                 };\r
642                 xnodes.length = 0;\r
643         };\r
644         return this;\r
645 };\r
646 \r
647 /* --------------------------------------\r
648  *  TODO destory -> kill\r
649  */\r
650 \r
651 function X_Node_destroy( isChild ){\r
652         var xnodes = this._xnodes, i, elm;\r
653         \r
654         if( !this._flags ) return;\r
655         \r
656         elm = this._rawObject || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );\r
657         \r
658         if( xnodes && ( i = xnodes.length ) ){\r
659                 //for( ; i; ){\r
660                 //      xnodes[ --i ].destroy( true );\r
661                 //};\r
662         };\r
663         elm && this._listeners && this.unlisten(); // イベントの退避\r
664 \r
665         if( this._flags & X_Node_State.IN_TREE ){\r
666                 !isChild && this.remove();\r
667                 delete this._flags;\r
668         } else {\r
669                 this.parent && this.parent._xnodes.splice( this.parent._xnodes.indexOf( this ), 1 );\r
670                 elm && !isChild && X_Node__actualRemove( this );\r
671                 this.kill();\r
672         };\r
673         \r
674         delete X_Node_CHASHE[ this._uid ];\r
675 };\r
676 \r
677 function X_Node_onBeforeKill( e ){\r
678         var xnodes = this._xnodes, i, elm;\r
679         \r
680         if( !this._flags ) return X.Callback.NONE;\r
681         \r
682         elm = this._rawObject || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );\r
683         elm && this._listeners && this.unlisten(); // イベントの退避\r
684 \r
685         if( xnodes && ( i = xnodes.length ) ){\r
686                 for( ; i; ){\r
687                         X_Node_onBeforeKill.call( xnodes[ --i ] );\r
688                 };\r
689         };\r
690 \r
691         delete X_Node_CHASHE[ this._uid ];\r
692 \r
693         if( e ){\r
694                 this.remove();\r
695                 if( X_Node_reserveRemoval[ X_Node_reserveRemoval.length - 1 ] === this ){\r
696                         delete this._flags;\r
697                         return X.Callback.PREVENT_DEFAULT;              \r
698                 };              \r
699         };\r
700         return X.Callback.NONE;\r
701 };\r
702 \r
703 \r
704 /* --------------------------------------\r
705  *  contains\r
706  */\r
707 function X_Node_contains( v ){\r
708         var elm, type, xnodes, i;\r
709         if( !v || !this._tag || this === v ) return false;\r
710         // contains ie4+\r
711         if( ( elm = this._rawObject || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this ) ) && document.contains && ( type = X_Node_getType( v ) ) && ( type === X_Node_TYPE.RAW_HTML || type === X_Node_TYPE.RAW_TEXT ) ){\r
712                 return elm.contains( v );       \r
713         };\r
714         //if( document.compareDocumentPosition ){\r
715         //      \r
716         //};\r
717         xnodes = this._xnodes;\r
718         if( !xnodes || !xnodes.length ) return false;\r
719         if( xnodes.indexOf( v ) !== -1 ) return true; // fast\r
720         if( elm === v.parentNode ) return true;\r
721         for( i = xnodes.length; i; ){\r
722                 if( xnodes[ --i ].contains( v ) ) return true;\r
723         };\r
724         return false;\r
725 };\r
726 \r
727 /* --------------------------------------\r
728  *  getChild\r
729  */\r
730 function X_Node_getChildAt( i ){\r
731         var xnodes = this._xnodes;\r
732         return xnodes && 0 <= i && i < xnodes.length && xnodes[ i ];\r
733 };\r
734 \r
735 function X_Node_length(){\r
736         var xnodes = this._xnodes;\r
737         return xnodes ? xnodes.length : 0;\r
738 };\r
739 \r
740 /* --------------------------------------\r
741  *  firstChild, lastChild\r
742  */\r
743 function X_Node_firstChild(){\r
744         return this.getChildAt( 0 );\r
745 };\r
746 function X_Node_lastChild(){\r
747         return this.getChildAt( this._xnodes.length - 1 );\r
748 };\r
749 \r
750 /* --------------------------------------\r
751  *  getOrder\r
752  */\r
753 function X_Node_getOrder(){\r
754         var parent = this.parent;\r
755         if( !parent ) return -1;\r
756         return parent._xnodes.indexOf( this );\r
757 };\r
758 \r
759 /* --------------------------------------\r
760  *  className, addClass, removeClass, hasClass\r
761  */\r
762 function X_Node_className( v ){\r
763         var node, _, __;\r
764         // getter\r
765         if( v === undefined ) return this._className;\r
766         \r
767         // setter\r
768         if( this._className === v ) return this;\r
769         if( !v || !X.Type.isString( v ) ){\r
770                 delete this._className;\r
771         } else {\r
772                 // cleanup\r
773                 _  = ' ';\r
774                 __ = '  ';\r
775                 while( v.indexOf( __ ) !== -1 ){ v = v.split( __ ).join( _ ); };\r
776                 v.charAt( 0 ) === _ && ( v = v.substr( 1 ) );\r
777                 v.lastIndexOf( _ ) === 0 && ( v = v.substr( 0, v.length - 1 ) );\r
778                 \r
779                 if( this._className === v ) return this;\r
780                 v ? ( this._className = v ) : delete this._className;\r
781         };\r
782         this._flags |= X_Node_State.DIRTY_CLASSNAME;\r
783         this._flags & X_Node_State.IN_TREE && X_Node_reserveUpdate();\r
784         return this;\r
785 };\r
786 function X_Node_addClass( v ){\r
787         var names = v.split( ' ' ),\r
788                 i     = names.length,\r
789                 name;\r
790         v = '';\r
791         for( ; i; ){\r
792                 name = names[ --i ];\r
793                 if( !name ) continue;\r
794                 !this.hasClass( name ) && ( v += ( v ? ' ' : '' ) + name );\r
795         };\r
796         return v ? this.className( this._className + ( this._className ? ' ' : '' ) + v ) : this;\r
797 };\r
798 function X_Node_removeClass( v ){\r
799         var _          = ' ',\r
800                 className  = this._className,\r
801                 names      = v.split( _ ),\r
802                 classNames, i, f, j;\r
803         if( !className ) return this;\r
804         for( classNames = className.split( _ ), i = classNames.length; i; ){\r
805                 className = classNames[ --i ];\r
806                 for( j = names.length; j; ){\r
807                         if( className === names[ --j ] ){\r
808                                 classNames.splice( i, 1 );\r
809                                 names.splice( j, 1 );\r
810                                 f = true;\r
811                                 break;\r
812                         };\r
813                 };\r
814         };\r
815         return f ? this.className( classNames.join( _ ) ) : this;\r
816 };\r
817 function X_Node_toggleClass( v, opt_toggle ){\r
818         var names, i, name;\r
819         if( opt_toggle !== undefined ){\r
820                 return !!opt_toggle ? this.addClass( v ) : this.removeClass( v );       \r
821         };\r
822         names = v.split( ' ' );\r
823         for( i = names.length; i; ){\r
824                 name = names[ --i ];\r
825                 this.hasClass( name ) ? this.removeClass( name ) : this.addClass( name );\r
826         };\r
827         return this;\r
828 };\r
829 function X_Node_hasClass( v ){\r
830         var _ = ' ',\r
831                 className = this._className,\r
832                 i, name;\r
833         if( className === v ) return true;\r
834         if( !className ) return false;\r
835         \r
836         className = _ + className + _;\r
837         if( className.indexOf( _ + v + _ ) !== -1 ) return true; // lucky hit\r
838         \r
839         for( v = v.split( _ ), i = v.length; i; ){\r
840                 name = v[ --i ];\r
841                 if( name === '' ) continue;\r
842                 if( className.indexOf( _ + name + _ ) === -1 ) return false;\r
843         };\r
844         return true;\r
845 };\r
846 \r
847 /* --------------------------------------\r
848  *  html, text\r
849  * \r
850  * outerHTML が欲しい場合は、xnode.call('outerHTML') とできる。\r
851  */\r
852 function X_Node_html( html ){\r
853         var _ = '', q = '"', xnodes, n, i, l;\r
854         // setter\r
855         if( html !== undefined ){ // String 以外に Number や false null なども許可\r
856                 if( !this._tag ) return this.text( html );\r
857                 return html ? this.empty().append.apply( this, X_HtmlParser_parse( html, true ) ) : this.empty();\r
858         };\r
859         \r
860         // getter\r
861         if( !this._tag ){\r
862                 return this._text;\r
863         };\r
864         \r
865         this._flags & X_Node_State.OLD_CSSTEXT && X_Node_CSS_objToCssText( this );\r
866 \r
867         html = !X_Node_outerXNode ? [] : [\r
868                 '<', this._tag,\r
869                 this._id ? ' id="' + this._id + q : _,\r
870                 this._className ? ' class="' + this._className + q : _,\r
871                 this._flags & X_Node_State.OLD_ATTRTEXT ? X_Node_Attr_objToAttrText( this ) : this._attrText,\r
872                 this._cssText ? ' style="' + this._cssText + q : _,\r
873         '>' ];\r
874         \r
875         n = html.length;\r
876         if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
877                 if( !X_Node_outerXNode ) X_Node_outerXNode = this;\r
878                 for( i = 0; i < l; ++i ){\r
879                         html[ n ] = xnodes[ i ].html();\r
880                         ++n;\r
881                 };\r
882                 if( X_Node_outerXNode === this ) X_Node_outerXNode = null;\r
883         };\r
884         !X_Node_outerXNode || X_Dom_DTD_EMPTY[ this._tag ] || ( html[ n ] = '<\/' + this._tag + '>' );\r
885         return html.join( _ );\r
886 };\r
887 \r
888 /*\r
889  * null が来たら '', 数値等が来たら文字列化\r
890  */\r
891 function X_Node_text( text ){\r
892         var xnodes, texts, i, l;\r
893         // setter\r
894         if( text !== undefined ){\r
895                 if( text === null ) text = '';\r
896                 text += '';\r
897                 \r
898                 if( !this._tag ){\r
899                         if( this._text !== text ){\r
900                                 text ? ( this._text = text ) : delete this._text;\r
901                                 this._flags |= X_Node_State.DIRTY_CONTENT;                              \r
902                                 this._flags & X_Node_State.IN_TREE && X_Node_reserveUpdate();\r
903                         };\r
904                         return this;\r
905                 };\r
906                 if( !text ) return this.empty();\r
907                 if( ( xnodes = this._xnodes ) && xnodes.length === 1 && !xnodes[ 0 ]._tag ){\r
908                         xnodes[ 0 ].text( text );\r
909                         return this;\r
910                 };\r
911                 this.empty().createText( text );\r
912                 return this;\r
913         };\r
914         // getter\r
915         if( this._tag ){\r
916                 if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
917                         for( texts = [], i = 0; i < l; ++i ){\r
918                                 texts[ i ] = xnodes[ i ].text();\r
919                         };\r
920                         return texts.join( '' );\r
921                 };\r
922                 return '';\r
923         };\r
924         return this._text;\r
925 };\r
926 \r
927 /*\r
928  * HTML要素に対して name の関数を実行しその戻り値を返す。関数に渡す引数も任意に設定できる。\r
929  */\r
930 function X_Node_call( name /*, opt_args... */ ){\r
931         var l = arguments.length - 1,\r
932                 raw, func, args, params, i;\r
933                 \r
934         X_Node_updateTimerID && X_Node_startUpdate();\r
935         \r
936         switch( name ){\r
937                 case 'nodeType' :\r
938                         return this._tag ? 1 : 3;\r
939                 case 'text' :\r
940                         return this.text();\r
941                 case 'html' :\r
942                 case 'innerHTML' :\r
943                         return this.html();\r
944                 case 'outerHTML' :\r
945                         X_Node_outerXNode = X_Node_body; // == true ならなんでもよい。型を合わすために xbody にしている\r
946                         v = this.html();\r
947                         X_Node_outerXNode = null;\r
948                         return v;\r
949                 case 'fontSize' :\r
950                         return X_Node_CSS_getCharSize( this );\r
951                 case 'inGPU' :\r
952                         return !!( this._flags & ( X_Node_State.GPU_NOW | X_Node_State.GPU_RELEASE_RESERVED ) );\r
953         };\r
954         \r
955         raw  = this._rawObject || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );\r
956         if( !raw ) return;\r
957         \r
958         if( name === 'scrollTo' ){\r
959                 raw.scrollLeft = arguments[ 1 ] || 0;\r
960                 raw.scrollTop  = arguments[ 2 ] || 0;\r
961                 return;\r
962         };\r
963         \r
964         func = raw[ name ];\r
965         if( X.Type.isFunction( func ) ){\r
966                 if( l ){\r
967                         args = X_Object_cloneArray( arguments );\r
968                         args.shift();\r
969                         return func.apply( raw, args );\r
970                 };\r
971                 return raw[ name ]();           \r
972         } else\r
973         if( X.Type.isUnknown( func ) ){\r
974                 // typeof func === unknown に対策\r
975                 // http://la.ma.la/blog/diary_200509031529.htm          \r
976                 if( l ){\r
977                         args = X_Object_cloneArray( arguments );\r
978                         args.shift();\r
979                         \r
980                 params = [];\r
981                 for( i = 0; i < l; ++i ){\r
982                         params[ i ] = '_' + i;\r
983                 };\r
984                 params = params.join( ',' );\r
985                 return Function(\r
986                         params,\r
987                     [ 'return this.', name, '(', params, ')' ].join( '' )\r
988                 ).apply( raw, args );\r
989                 };\r
990                 return raw[ name ]();\r
991         };\r
992 };\r
993 \r
994 /*\r
995  * xnode を this として関数を実行する。 NodeList.each と動作を合わせてあるため関数の戻り値は破棄される。\r
996  * 関数に渡す引数も任意に設定できる。\r
997  */\r
998 function X_Node_each( func /*, opt_args */ ){\r
999         var args;\r
1000         if( 1 < arguments.length ){\r
1001                 args = X_Object_cloneArray( arguments );\r
1002                 args[ 0 ] = 0;          \r
1003                 func.apply( this, args );\r
1004         } else {\r
1005                 func.call( this, 0 );\r
1006         };\r
1007         return this;\r
1008 };\r
1009 \r
1010 \r
1011 /* --------------------------------------\r
1012  *  Async commit update\r
1013  * \r
1014  * TODO Timer や DOM イベントの呼び出しの最後に、まだ一度も commitUpdate していないなら commitUpdate してしまう。\r
1015  */\r
1016         \r
1017 function X_Node_reserveUpdate(){\r
1018         if( !X_Node_updateTimerID ) X_Node_updateTimerID = X.Timer.requestFrame( X_Node_startUpdate );\r
1019 };\r
1020 \r
1021 var X_Node_updateReservedByReleaseGPU = false;\r
1022 \r
1023 function X_Node_startUpdate( time ){\r
1024         var removal, i, xnode;\r
1025         \r
1026         if( !X_Node_updateTimerID || X_ViewPort_readyState < X_TEMP.SYSTEM_EVENT_INIT ){\r
1027                 return;\r
1028         };\r
1029 \r
1030         X.Timer.cancelFrame( X_Node_updateTimerID );\r
1031         X_Node_updateTimerID = 0;\r
1032 \r
1033         if( time ){\r
1034                 // X.Timer 経由でないと発火しない このイベントでサイズを取ると無限ループに\r
1035                 X_System._listeners && X_System._listeners[ X.Event.BEFORE_UPDATE ] && X_System.dispatch( X.Event.BEFORE_UPDATE );\r
1036         };\r
1037 \r
1038         removal = X_Node_reserveRemoval;\r
1039 \r
1040         if( i = removal.length ){\r
1041                 for( ; i; ){\r
1042                         xnode = removal[ --i ];\r
1043                         // TODO GPU レイヤーの子の場合、remove をスキップする。 非GPU レイヤーへ apppend される場合、clone する?\r
1044                         X_Node__actualRemove( xnode );\r
1045                         !xnode._flags && xnode.kill();\r
1046                 };\r
1047                 removal.length = 0;\r
1048         };\r
1049         \r
1050         if( X_Node_html._flags & X_Node_BitMask_IS_DIRTY ){\r
1051                 X_Node__commitUpdate( X_Node_html, X_Node_html._rawObject.parentNode, null, X_Node_html._flags );\r
1052         } else {\r
1053                 X_Node__commitUpdate( X_Node_head, X_Node_head._rawObject.parentNode, null, X_Node_head._flags );\r
1054                 X_Node__commitUpdate( X_Node_body, X_Node_body._rawObject.parentNode, null, X_Node_body._flags );\r
1055         };\r
1056         \r
1057         if( X_Node_updateReservedByReleaseGPU ){\r
1058                 X_Node_reserveUpdate();\r
1059                 X_Node_updateReservedByReleaseGPU = false;\r
1060         };\r
1061         \r
1062         if( time ){\r
1063                 // X.Timer 経由でないと発火しない このイベントでサイズを取ると無限ループに\r
1064                 X_System._listeners && X_System._listeners[ X.Event.UPDATED ] && X_System.dispatch( X.Event.UPDATED );  \r
1065         };\r
1066         \r
1067         X_ViewPort._listeners && X_ViewPort._listeners[ X.Event.AFTER_UPDATE ] && X_ViewPort.asyncDispatch( X.Event.AFTER_UPDATE );\r
1068 };\r
1069 \r
1070 /*\r
1071  * 1. GPU_NOW の場合、子の変更は行わない\r
1072  * 2. GPU解放予約 の場合//、この要素のみ変更を行う。rAF 後にさらに更新するためフラグを立てる。\r
1073  * 3. GPU予約 -> GPU\r
1074  * 4. style="display:none" の場合、これ以下の変更を行わない。\r
1075  * 5. ie5 非表示フラグが立っていて、親と自身の class・id によって非表示になっていて、親と自身に変更がない。accumulatedFlags を使用。\r
1076  *     -> TODO これ TREE の変更を検出できない。 remove したときに 子まで X_Node_State.IE5_DISPLAY_NONE_FIXを落とす。\r
1077  * 6. 要素の生成\r
1078  * 7. 要素の位置のズレを補正\r
1079  * 8. 更新の適用\r
1080  * 9. ie5 親及び自身へのクラス・id指定で display:none になるケースがありそれを検出。\r
1081  *   このままでは、生成と破棄が繰り返されてしまうので親と自身のクラス・idが変わった場合、ツリー位置の変化があった場合に再生する。\r
1082  */\r
1083 var X_Node__commitUpdate =\r
1084         X_UA_DOM.W3C ?\r
1085                 ( function( that, parentElement, nextElement, accumulatedFlags ){\r
1086                         var elm = that._rawObject,\r
1087                                 created, xnodes, l, next;\r
1088 \r
1089                         // 1. GPU 一切の更新をスキップ\r
1090                         if( that._flags & X_Node_State.GPU_NOW ){\r
1091                                 console.log( '更新のskip ' + !!( that._flags & X_Node_BitMask_IS_DIRTY ) );\r
1092                                 that._flags & X_Node_BitMask_IS_DIRTY && X_Node__updateRawNode( that, elm );\r
1093                                 return elm;\r
1094                         };\r
1095 \r
1096                         // 2. GPU解放予約\r
1097                         // TODO もしかしたらこのタイミングで更新できるかも。\r
1098                         if( that._flags & X_Node_State.GPU_RELEASE_RESERVED ){\r
1099                                 console.log( 'GPU 解放 ' );\r
1100                                 //X_Node_updateReservedByReleaseGPU = true;\r
1101                                 //X_Node__updateRawNode( that, elm );\r
1102                                 that._flags &= X_Node_BitMask_RESET_GPU;\r
1103                                 //return elm;\r
1104                         };\r
1105 \r
1106                         // 3. GPU予約 -> GPU\r
1107                         if( that._flags & X_Node_State.GPU_RESERVED ){\r
1108                                 that._flags &= X_Node_BitMask_RESET_GPU;\r
1109                                 that._flags |= X_Node_State.GPU_NOW;\r
1110                         };\r
1111 \r
1112                         // 4. style="display:none" の場合\r
1113                         if( that._flags & X_Node_State.STYLE_IS_DISPLAY_NONE ){\r
1114                                 if( X_Node_displayNoneFixForIE5 ){\r
1115                                         // filter の効いている要素を含む要素は display:none が無視される。\r
1116                                         // filter = '' で削除はできるが、再表示時に filter が消える。 -> filter な要素を削除してしまう。                                         \r
1117                                         if( elm && elm.parentNode ){\r
1118                                                 X_Node__actualRemove( that );\r
1119                                         };\r
1120                                         return nextElement;\r
1121                                 };\r
1122                                 elm && ( elm.style.display = 'none' );\r
1123                                 return ( elm && elm.nextSibling === nextElement ) ? elm : nextElement;\r
1124                         };\r
1125                         \r
1126                         // 5. ie5 非表示fixフラグ\r
1127                         accumulatedFlags |= that._flags;\r
1128                         \r
1129                         if( that._flags & X_Node_State.IE5_DISPLAY_NONE_FIX ){\r
1130                                 if( accumulatedFlags & ( X_Node_State.DIRTY_POSITION | X_Node_State.DIRTY_ID | X_Node_State.DIRTY_CLASSNAME ) === 0 ){\r
1131                                         return nextElement;\r
1132                                 };\r
1133                         };\r
1134                         \r
1135                         // 6. 要素の生成\r
1136                         if( !elm ){\r
1137                                 if( !that._tag ){\r
1138                                         that._flags &= X_Node_BitMask_RESET_DIRTY;\r
1139                                         that._rawObject = elm = document.createTextNode( X_String_chrReferanceTo( that._text ) );\r
1140                                         if( !X.UA.IE ){\r
1141                                                 elm.UID = that._uid;\r
1142                                         };\r
1143                                 } else\r
1144                                 if( X_Node_strictElmCreation ){\r
1145                                         that._flags & X_Node_State.OLD_CSSTEXT && X_Node_CSS_objToCssText( that, true ); // OLD_CSSTEXT ??\r
1146                 \r
1147                                         that._rawObject = elm =\r
1148                                                 document.createElement( [\r
1149                                                         '<', that._tag,\r
1150                                                                 ' UID="', that._uid, '"',\r
1151                                                                 that._id ? ' id="' + that._id + '"' : '',\r
1152                                                                 that._className ? ' class="' + that._className + '"' : '',\r
1153                                                                 X_Node_Attr_objToAttrText( that, true ),\r
1154                                                                 that._cssText ? ' style="' + that._cssText + '"' : '',\r
1155                                                         '>' ].join( '' ) );\r
1156                                 } else {\r
1157                                         that._rawObject = elm = document.createElement( that._tag );\r
1158                                 };\r
1159                                 \r
1160                                 // IE には要素追加のタイミングで起こるメモリリークがありここで追加\r
1161                                 if( !X_Node_addTreeAfterChildren ){\r
1162                                         nextElement ?\r
1163                                                 parentElement.insertBefore( elm, nextElement ) :\r
1164                                                 parentElement.appendChild( elm );\r
1165                                 };\r
1166 \r
1167                                 if( that._tag ){\r
1168                                         X_EventDispatcher_toggleAllEvents( that, true );// イベントの復帰                                \r
1169                                         that._flags |= X_Node_State.ACTUAL_LISTENING;\r
1170                                         \r
1171                                         if( X_Node_documentFragment ){\r
1172                                                 //( frg = X_Node_documentFragment ).appendChild( elm );\r
1173                                         };\r
1174 \r
1175                                         if( X_Node_strictElmCreation ){\r
1176                                                 that._flags &= X_Node_BitMask_RESET_DIRTY;\r
1177                                                 // ie の string から要素を作る場合、ネットワーク系属性は onload イベントなどを拾うために、要素生成->イベント復帰後に適用する\r
1178                                                 that._newAttrs && ( that._flags |= X_Node_State.DIRTY_ATTR ); // Network 系の属性は遅らせて設定\r
1179                                                 that._flags |= X_Node_State.DIRTY_IE_FILTER;// doc 追加後に filter を指定しないと有効にならない。\r
1180                                         } else {\r
1181                                                 elm.UID = that._uid;\r
1182                                                 that._newAttrs = that._attrs;\r
1183                                                 that._flags &= X_Node_BitMask_RESET_DIRTY;\r
1184                                                 that._flags |= X_Node_State.DIRTY_ID | X_Node_State.DIRTY_CLASSNAME | X_Node_State.DIRTY_ATTR | X_Node_State.DIRTY_CSS | X_Node_State.DIRTY_IE_FILTER;\r
1185                                                 \r
1186                                                 // http://outcloud.blogspot.jp/2010/09/iframe.html\r
1187                                                 // この問題は firefox3.6 で確認\r
1188                                                 if( X_UA.Gecko ){\r
1189                                                         if( that._tag === 'IFRAME' && ( !that._attrs || !that._attrs[ 'src' ] ) ){\r
1190                                                                 //elm.contentWindow.location.replace = elm.src = 'about:blank';\r
1191                                                                 that.attr( 'src', 'about:blank' );\r
1192                                                         };\r
1193                                                 };\r
1194                                         };\r
1195                                 };\r
1196                                 \r
1197                                 created = true;\r
1198                         } else\r
1199                         // 7. 要素の位置のズレを補正\r
1200                         if( elm.parentNode !== parentElement || ( nextElement && elm.nextSibling !== nextElement ) ){\r
1201                                 nextElement ?\r
1202                                         parentElement.insertBefore( elm, nextElement ) :\r
1203                                         parentElement.appendChild( elm );\r
1204                         };\r
1205                         \r
1206                         if( that._listeners && ( that._flags & X_Node_State.ACTUAL_LISTENING ) === 0 ){\r
1207                                 X_EventDispatcher_toggleAllEvents( that, true );// イベントの退避\r
1208                                 that._flags |= X_Node_State.ACTUAL_LISTENING;\r
1209                         };\r
1210                         \r
1211                         // 8. 更新の適用\r
1212                         if( accumulatedFlags & X_Node_BitMask_IS_DIRTY ){\r
1213                                 delete that._fontSize;\r
1214                                 X_Node__updateRawNode( that, elm );\r
1215                         };\r
1216 \r
1217                         // 9. ie5 only\r
1218                         // 親及び自身へのクラス・id指定で display : none になるケースがありそれを検出\r
1219                         // 生成と破棄が繰り返されてしまう、親と自身の id, class が変わった場合だけ再生成。 accumulatedFlags & ( ID | CLASSNAME )\r
1220                         // currentStyle を観ていたときはエラーで停止する、alert と挟むと正常に動いて支離滅裂\r
1221                         if( X_Node_displayNoneFixForIE5 && that._tag ){\r
1222                                 if( elm.runtimeStyle.display === 'none' ){\r
1223                                         X_Node__actualRemove( that );\r
1224                                         that._flags |= X_Node_State.IE5_DISPLAY_NONE_FIX;\r
1225                                         return nextElement;                                     \r
1226                                 } else {\r
1227                                         that._flags &= ~X_Node_State.IE5_DISPLAY_NONE_FIX;\r
1228                                 };\r
1229                         };\r
1230                         \r
1231                         // 10. 子要素の更新。\r
1232                         if( ( xnodes = that._xnodes ) && ( l = xnodes.length ) ) {\r
1233                                 for( ; l; ){\r
1234                                         next = X_Node__commitUpdate( xnodes[ --l ], elm, next, accumulatedFlags );\r
1235                                 };\r
1236                         };\r
1237 \r
1238                         if( created && X_Node_addTreeAfterChildren ){\r
1239                                 nextElement ?\r
1240                                         parentElement.insertBefore( elm, nextElement ) :\r
1241                                         parentElement.appendChild( elm );\r
1242                                 \r
1243                                 if( X_UA.Gecko && that._tag === 'IFRAME' && elm.contentWindow ){\r
1244                                         // tree に追加されるまで contentWindow は存在しない。\r
1245                                         elm.contentWindow.location.replace = elm.src;\r
1246                                 };\r
1247                         };\r
1248 \r
1249                         return elm;\r
1250                 }) :\r
1251         X_UA_DOM.IE4 ? \r
1252                 ( function( that, parentElement, prevElement, accumulatedFlags ){\r
1253                         var elm = that._rawObject || X_Node__ie4getRawNode( that ),\r
1254                                 xnodes, l, i, dirty, mix, html, text, prev;\r
1255 \r
1256                         if( !that._tag ){\r
1257                                 that._flags & X_Node_State.DIRTY_CONTENT && X_Node__updateRawNode( that, elm );\r
1258                                 return elm;\r
1259                         };\r
1260                         \r
1261                         // 4. style="display:none" の場合\r
1262                         if( that._flags & X_Node_State.STYLE_IS_DISPLAY_NONE ){\r
1263                                 if( elm ){\r
1264                                         elm.style.display = 'none';\r
1265                                         if( elm.style.display !== 'none' ){ // ie4 の style は currentStyle 相当らしい、、、? div 以外への display:none が効かないので remove する。\r
1266                                                 X_Node__actualRemove( that );\r
1267                                                 return prevElement;\r
1268                                         };\r
1269                                 };\r
1270                                 return elm || prevElement;\r
1271                         };\r
1272                         \r
1273                         if( !elm ){\r
1274                                 prevElement ?\r
1275                                         prevElement.insertAdjacentHTML( 'AfterEnd', X_Node__actualCreate( that, false ) ) :\r
1276                                         parentElement.insertAdjacentHTML( 'AfterBegin', X_Node__actualCreate( that, false ) );\r
1277                                 X_Node__afterActualCreate( that );\r
1278                                 return that._rawObject || X_Node__ie4getRawNode( that );\r
1279                         };\r
1280                         \r
1281                         accumulatedFlags |= that._flags;\r
1282                         \r
1283                         xnodes = that._xnodes;\r
1284                         l      = xnodes ? xnodes.length : 0;\r
1285                         dirty  = !!( that._flags & X_Node_State.IE4_DIRTY_CHILDREN );\r
1286                         \r
1287                         /*\r
1288                          * HTML の下に TextNode だけ 。MIX_FIXED でない場合、削除、追加 を親に通知\r
1289                          * HTML の下に HTML だけ\r
1290                          * HTML の下は MIX -> TextNode, html の削除、変更、追加\r
1291                          * HTML の下は MIX_FIXED -> TextNode を <font> に置き換えてあるのでW3C DON 的に触ることができる\r
1292                          */\r
1293                         if( dirty ){\r
1294                                 that._flags &= ~X_Node_State.IE4_DIRTY_CHILDREN;\r
1295                                 for( i = 0; i < l; ++i ){\r
1296                                         if( xnodes[ i ]._tag ){\r
1297                                                 that._flags |= X_Node_State.IE4_HAS_ELEMENT;\r
1298                                         } else {\r
1299                                                 that._flags |= X_Node_State.IE4_HAS_TEXTNODE;\r
1300                                         };\r
1301                                         if( that._flags & X_Node_BitMask_IE4_IS_MIX === X_Node_BitMask_IE4_IS_MIX ){\r
1302                                                 mix = true;\r
1303                                                 break;\r
1304                                         };\r
1305                                 };\r
1306                         };\r
1307                         \r
1308                         if( that._flags & X_Node_State.IE4_FIXED || that._flags & X_Node_BitMask_IE4_IS_MIX === X_Node_State.IE4_HAS_ELEMENT ){\r
1309                                 for( i = 0; i < l; ++i ){\r
1310                                         prev = X_Node__commitUpdate( xnodes[ i ], elm, prev, accumulatedFlags );\r
1311                                 };\r
1312                         } else\r
1313                         if( mix ){\r
1314                                 html = [];\r
1315                                 for( i = 0; i < l; ++i ){\r
1316                                         html[ i ] = X_Node__actualCreate( xnodes[ i ], false );\r
1317                                 };\r
1318                                 elm.innerHTML = html.join( '' );\r
1319                                 for( i = 0; i < l; ++i ){\r
1320                                         X_Node__afterActualCreate( xnodes[ i ] );\r
1321                                 };\r
1322                                 that._flags |= X_Node_State.IE4_FIXED;\r
1323                         } else\r
1324                         if( that._flags & X_Node_State.IE4_HAS_TEXTNODE ){\r
1325                                 dirty = dirty || false;\r
1326                                 for( i = 0; i < l; ++i ){\r
1327                                         text = xnodes[ i ];\r
1328                                         if( text._flags & X_Node_BitMask_IS_DIRTY ){\r
1329                                                 text._flags &= X_Node_BitMask_RESET_DIRTY;\r
1330                                                 dirty = true;\r
1331                                         };\r
1332                                 };\r
1333                                 if( dirty ) elm.innerHTML = that.text();\r
1334                         };\r
1335                         \r
1336                         if( accumulatedFlags & X_Node_BitMask_IS_DIRTY ) delete that._fontSize;\r
1337                         \r
1338                         that._flags &= ~X_Node_State.DIRTY_POSITION;\r
1339                         that._flags & X_Node_BitMask_IS_DIRTY && X_Node__updateRawNode( that, elm );\r
1340                         return elm;\r
1341                 }) :\r
1342                 (function(){});\r
1343 \r
1344 /*\r
1345  * GPU レイヤーするブラウザは、子要素から変更を当てていく? <- とりあえず、親要素から。\r
1346  */\r
1347 var X_Node__updateRawNode =\r
1348         X_UA_DOM.W3C ?\r
1349                 ( function( that, elm ){\r
1350                         var attrs, rename, k, v;\r
1351 \r
1352                         // textNode\r
1353                         if( !that._tag ){\r
1354                                 elm.data = X_String_chrReferanceTo( that._text );\r
1355                                 that._flags &= X_Node_BitMask_RESET_DIRTY;\r
1356                                 return;\r
1357                         };\r
1358                         // id\r
1359                         if( that._flags & X_Node_State.DIRTY_ID ){\r
1360                                 that._id ? ( elm.id = that._id ) : ( elm.id && elm.removeAttribute( 'id' ) );           \r
1361                         };\r
1362                         // className\r
1363                         if( that._flags & X_Node_State.DIRTY_CLASSNAME ){\r
1364                                 that._className ? ( elm.className = that._className ) : ( elm.className && elm.removeAttribute( X_UA.IE < 8 ? 'className' : 'class' ) ); // className は ie7-                  \r
1365                         };\r
1366                         \r
1367                         // attr\r
1368                         if( that._flags & X_Node_State.DIRTY_ATTR && ( attrs = that._newAttrs || that._attrs ) ){\r
1369                                 rename = X_Node_Attr_renameForDOM;\r
1370                                                 \r
1371                                 for( k in attrs ){\r
1372                                         v = attrs[ k ];\r
1373                                         \r
1374                                         switch( that._tag + k ){\r
1375                                                 case 'TEXTAREAvalue' :\r
1376                                                         // IETester 5.5 ではエラーが出なかった.MultipulIE5.5 ではエラーが出たので\r
1377                                                         if( !X_UA.MacIE && X_UA.IE5x ){\r
1378                                                                 elm.firstChild ?\r
1379                                                                         ( elm.firstChild.data = v || '' ) :\r
1380                                                                         elm.appendChild( document.createTextNode( v || '' ) );\r
1381                                                                 continue;\r
1382                                                         };\r
1383                                                         break;\r
1384                                                 \r
1385                                                 case 'IFRAMEsrc' :\r
1386                                                         // http://outcloud.blogspot.jp/2010/09/iframe.html\r
1387                                                         // この問題は firefox3.6 で確認\r
1388                                                         if( X_UA.Gecko && elm.contentWindow ){\r
1389                                                                 elm.contentWindow.location.replace = elm.src = v || '';\r
1390                                                                 continue;\r
1391                                                         };\r
1392                                                         break;\r
1393                                                 \r
1394                                                 case 'IFRAMEname' :\r
1395                                                         // http://d.hatena.ne.jp/NeoCat/20080921/1221940658\r
1396                                                         // こちらに名前をsetしないとtargetが動作しない\r
1397                                                         // これってあとから name を変更できないバグでは? itozyun\r
1398                                                         // if( X_UA.IE ) elm.name = elm.contentWindow.name = v || '';\r
1399                                         };\r
1400                                         \r
1401                                         //if( X_EMPTY_OBJECT[ k ] ) continue;\r
1402                                         // TODO IE では input, なぜか button, object も type, name の変更が出来ない、同値で置き換えようとしても不可\r
1403                                         v === undefined ?\r
1404                                                 elm.removeAttribute( rename[ k ] || k ) :\r
1405                                                 ( elm[ rename[ k ] || k ] = X_Node_Attr_noValue[ k ] ? k : v );\r
1406                                 };\r
1407                                 delete that._newAttrs;\r
1408                         };\r
1409                         \r
1410                         // style\r
1411                         if( that._flags & X_Node_State.DIRTY_CSS ){\r
1412                                 if( that._flags & X_Node_State.OLD_CSSTEXT ? X_Node_CSS_objToCssText( that ) : that._cssText ){\r
1413                                         X_UA.Opera78 || X_UA.NN6 ?\r
1414                                                 elm.setAttribute( 'style', that._cssText ) : // opera8用\r
1415                                                 ( elm.style.cssText = that._cssText );\r
1416                                 } else {\r
1417                                         elm.style.cssText = ''; // IE5.5以下 Safari3.2 で必要\r
1418                                         elm.removeAttribute( 'style' );\r
1419                                 };\r
1420                         } else\r
1421                         if( that._flags & X_Node_State.DIRTY_IE_FILTER ){\r
1422                                 v = X_Node_CSS_objToIEFilterText( that );\r
1423                                 if( v ){\r
1424                                         elm.style.filter = v;\r
1425                                         that._flags |= X_Node_State.IE_FILTER_NOW;\r
1426                                 } else {\r
1427                                         elm.style.removeAttribute( 'filter' );\r
1428                                         that._flags &= ~X_Node_State.IE_FILTER_NOW;\r
1429                                 };\r
1430                         };\r
1431                         \r
1432                         that._flags &= X_Node_BitMask_RESET_DIRTY;\r
1433                 }) :\r
1434         X_UA_DOM.IE4 ? \r
1435                 ( function( that, elm ){\r
1436                         var attrs, rename, k, v;\r
1437 \r
1438                         // fake textNode\r
1439                         if( !that._tag ){\r
1440                                 elm.innerText = that._text;\r
1441                                 that._flags &= X_Node_BitMask_RESET_DIRTY;\r
1442                                 return;\r
1443                         };\r
1444                         \r
1445                 /*\r
1446                  * http://www.tohoho-web.com/js/element.htm\r
1447                  * title、className、id、lang、language には setAttribute でなく、element.id で直接読み書きできる\r
1448                  */     \r
1449                         // id\r
1450                         if( that._flags & X_Node_State.DIRTY_ID ) elm.setAttribute( 'id', that._id || ( 'ie4uid' + that._uid ) );\r
1451 \r
1452                         // className\r
1453                         if( that._flags & X_Node_State.DIRTY_CLASSNAME ){\r
1454                                 that._className ? ( elm.className = that._className ) : elm.removeAttribute( 'class' );\r
1455                         };\r
1456                         // style\r
1457                         if( that._flags & X_Node_State.DIRTY_CSS ){\r
1458                                 if( that._flags & X_Node_State.OLD_CSSTEXT ? X_Node_CSS_objToCssText( that ) : that._cssText ){\r
1459                                         elm.style.cssText = that._cssText;\r
1460                                 } else {\r
1461                                         elm.style.cssText = '';\r
1462                                         elm.removeAttribute( 'style' );\r
1463                                 };\r
1464                         } else\r
1465                         if( that._flags & X_Node_State.DIRTY_IE_FILTER ){\r
1466                                 v = X_Node_CSS_objToIEFilterText( that );\r
1467                                 if( v ){\r
1468                                         elm.style.filter = v;\r
1469                                         that._flags |= X_Node_State.IE_FILTER_NOW;\r
1470                                 } else {\r
1471                                         elm.style.removeAttribute( 'filter' );\r
1472                                         that._flags &= ~X_Node_State.IE_FILTER_NOW;\r
1473                                 };\r
1474                         };\r
1475                         \r
1476                         // attr\r
1477                         if( that._flags & X_Node_State.DIRTY_ATTR && ( attrs = that._newAttrs || that._attrs ) ){\r
1478                                 rename = X_Node_Attr_renameForDOM;\r
1479                                 for( k in attrs ){\r
1480                                         //if( X_EMPTY_OBJECT[ k ] ) continue;\r
1481                                         ( v = attrs[ k ] ) === undefined ?\r
1482                                                 elm.removeAttribute( rename[ k ] || k ) :\r
1483                                                 elm.setAttribute( rename[ k ] || k, X_Node_Attr_noValue[ k ] ? k : v );\r
1484                                 };\r
1485                                 delete that._newAttrs;\r
1486                         };\r
1487 \r
1488                         that._flags &= X_Node_BitMask_RESET_DIRTY;\r
1489                 }) :\r
1490                 (function(){});\r
1491 \r
1492 /* --------------------------------------\r
1493  *  Create\r
1494  * \r
1495  * http://d.hatena.ne.jp/uupaa/20080718/1216362040\r
1496  * DOM Rangeが使える環境(Firefox2+,Opera9+,Safari3+)なら、innerHTMLいらずで、ガーって書けます。\r
1497  * return document.createRange().createContextualFragment("<div><select><option></option></select></div>");\r
1498  * insertAdjacentHTML\r
1499  * \r
1500  * ie7 以下では iframe の frameborder や、input name は、createElement 後に setAttribute しても無視される\r
1501  * \r
1502  * fragument がある場合 children も足して\r
1503  * Mozilla: 1.0+, IE: 5.5+, Netscape: 2.0+, Safari: 1.0+, Opera: 7.0+\r
1504  * ie6 大丈夫?fragment の場合リークしないか?チェックが必要\r
1505  * http://msdn.microsoft.com/ja-jp/library/bb250448%28v=vs.85%29.aspx\r
1506  * \r
1507  * document.createElement of ie4 is only for OPTION & IMAGE.\r
1508  */\r
1509 var X_Node__actualCreate =\r
1510         X_UA_DOM.IE4 && (function( that, isChild ){\r
1511                 var uid = that._uid,\r
1512                         html, xnodes, n, i, l;\r
1513                 \r
1514                 if( !that._tag ){\r
1515                         html = [ '<FONT id=ie4uid', uid, ' UID="', uid, '">', that._text, '</FONT>' ];// fake textNode\r
1516                         delete that._rawObject;\r
1517                 } else {\r
1518                         if( !isChild ) X_Node__actualRemove( that, /* true */ false );\r
1519                         \r
1520                         that._flags & X_Node_State.OLD_CSSTEXT && X_Node_CSS_objToCssText( that, true );\r
1521                         \r
1522                         html = [\r
1523                                 '<', that._tag, ' id=', ( that._id || ( 'ie4uid' + uid ) ), ' UID="', uid, '"',\r
1524                                 that._className ? ' class="' + that._className + '"' : '',\r
1525                                 X_Node_Attr_objToAttrText( that, true ),\r
1526                                 that._cssText ? ' style="' + that._cssText + '"' : '',\r
1527                         '>' ];\r
1528                         \r
1529                         n = html.length;\r
1530                         if( ( xnodes = that._xnodes ) && ( l = xnodes.length ) ){\r
1531                                 \r
1532                                 that._flags &= ~X_Node_State.IE4_DIRTY_CHILDREN;\r
1533                                 for( i = 0; i < l; ++i ){\r
1534                                         if( xnodes[ i ]._tag ){\r
1535                                                 that._flags |= X_Node_State.IE4_HAS_ELEMENT;\r
1536                                         } else {\r
1537                                                 that._flags |= X_Node_State.IE4_HAS_TEXTNODE;\r
1538                                         };\r
1539                                         if( that._flags & X_Node_BitMask_IE4_IS_MIX === X_Node_BitMask_IE4_IS_MIX ){\r
1540                                                 break;\r
1541                                         };\r
1542                                 };\r
1543                                 \r
1544                                 if( that._flags & X_Node_BitMask_IE4_IS_MIX === X_Node_State.IE4_HAS_TEXTNODE ){\r
1545                                         // only textnode\r
1546                                         html[ n ] = that.text();\r
1547                                         ++n;\r
1548                                 } else {\r
1549                                         for( i = 0; i < l; ++i ){\r
1550                                                 html[ n ] = X_Node__actualCreate( xnodes[ i ], true );\r
1551                                                 ++n;\r
1552                                         };\r
1553                                         that._flags |= X_Node_State.IE4_FIXED;\r
1554                                 };\r
1555                         };\r
1556                         X_Dom_DTD_EMPTY[ that._tag ] || ( html[ n ] = '<\/' + that._tag + '>' );\r
1557                         \r
1558                         that._newAttrs && ( that._flags |= X_Node_State.DIRTY_ATTR );\r
1559                 };\r
1560                 \r
1561                 return html.join( '' );\r
1562         });\r
1563 \r
1564 var X_Node__afterActualCreate =\r
1565         X_UA_DOM.IE4 && (function( that ){\r
1566                 var xnodes, i, v;\r
1567                 \r
1568                 if( !that._tag ) return that;\r
1569                 \r
1570                 if( ( xnodes = that._xnodes ) && ( i = xnodes.length ) ){\r
1571                         for( ; i; ){\r
1572                                 X_Node__afterActualCreate( xnodes[ --i ] );\r
1573                         };\r
1574                 };\r
1575                 // ネットわーう系属性と filter は要素生成後に適用\r
1576                 if( that._flags & ( X_Node_State.DIRTY_ATTR | X_Node_State.DIRTY_IE_FILTER ) ){\r
1577                         X_Node__updateRawNode( that, that._rawObject || X_Node__ie4getRawNode( that ) );\r
1578                 } else {\r
1579                         that._flags &= X_Node_BitMask_RESET_DIRTY;\r
1580                 };\r
1581                 X_EventDispatcher_toggleAllEvents( that, true );// イベントの復帰\r
1582         });\r
1583 \r
1584 var X_Node__actualRemove =\r
1585         X_UA_DOM.W3C ?\r
1586                 // GPUレイヤーにいるうちは remove しない。-> GPU解除してから remove する\r
1587                 // Firefox34 では遭遇せず、Safari で何度かアニメーションしているうちに発生\r
1588                 ( function( that, isChild ){\r
1589                         var xnodes = that._xnodes,\r
1590                                 elm    = that._rawObject,\r
1591                                 child, i, l;\r
1592 \r
1593                         if( xnodes && ( l = xnodes.length ) ){\r
1594                                 for( i = 0; i < l; ++i ){\r
1595                                         child = xnodes[ i ];\r
1596                                         child._tag && X_Node__actualRemove( child, true );\r
1597                                 };\r
1598                         };\r
1599 \r
1600                         if( !elm ) return;\r
1601                         \r
1602                         if( that._flags & X_Node_State.ACTUAL_LISTENING ){\r
1603                                 that._listeners && X_EventDispatcher_toggleAllEvents( that, false );// イベントの退避\r
1604                                 that._flags &= ~X_Node_State.ACTUAL_LISTENING;\r
1605                         };\r
1606                         \r
1607                         // ie5では filter の効いている要素をremove時に破棄して、再度append 時に新規生成する\r
1608                         // ちなみに elm.filters に触ると ie8 でなぜかカラム落ちが発生、、、\r
1609                         if( X_Node_displayNoneFixForIE5 ){\r
1610                                 if( elm.filters && elm.filters.length ){\r
1611                                         //elm.style.removeAttribute( 'filter' );\r
1612                                         isChild = false;\r
1613                                         delete that._rawObject;\r
1614                                         // 破棄前にインタラクティブな属性値を控える\r
1615                                         if( X_Node_Attr_HAS_VALUE[ that._tag ] && ( !that._newAttrs || !X_Object_inObject( 'value', that._newAttrs ) ) ){\r
1616                                                 if( !that._attrs ) that._attrs = {};\r
1617                                                 that._attrs.value = elm.value;\r
1618                                         };\r
1619                                         if( that._tag === 'OPTION' && ( !that._newAttrs || !X_Object_inObject( 'selected', that._newAttrs ) ) ){\r
1620                                                 if( !that._attrs ) that._attrs = {};\r
1621                                                 that._attrs.selected = elm.selected;\r
1622                                         };\r
1623                                         if( that._tag === 'SELECT' && ( !that._newAttrs || !X_Object_inObject( 'selectedIndex', that._newAttrs ) ) ){\r
1624                                                 if( !that._attrs ) that._attrs = {};\r
1625                                                 that._attrs.selectedIndex = elm.selectedIndex;\r
1626                                         };\r
1627                                         if( that._tag === 'INPUT' && that._attr && ( that._attr.type === 'checkbox' || that._attr.type === 'radio' ) && ( !that._newAttrs || !X_Object_inObject( 'checked', that._newAttrs ) ) ){\r
1628                                                 that._attrs.checked = elm.checked;\r
1629                                         };\r
1630                                         // 子要素への参照を外す\r
1631                                         elm.innerHTML = '';\r
1632                                 };\r
1633                         };\r
1634                         \r
1635                         if( !X_UA.MacIE ){\r
1636                                 // elm.parentNode.tagName for ie7\r
1637                                 !isChild && elm.parentNode && elm.parentNode.tagName && elm.parentNode.removeChild( elm );\r
1638                         } else {\r
1639                                 !isChild && elm.parentNode && elm.parentNode.tagName && X_TEMP._fixed_remove( elm, that );\r
1640                         };\r
1641                 }) :\r
1642         X_UA_DOM.IE4 ?\r
1643                 ( function( that, isChild ){\r
1644                         var xnodes = that._xnodes,\r
1645                                 elm    = that._rawObject || X_Node__ie4getRawNode( that ),\r
1646                                 i, l, xnode;\r
1647                         if( xnodes && ( l = xnodes.length ) ){\r
1648                                 for( i = 0; i < l; ++i ){\r
1649                                         X_Node__actualRemove( xnodes[ i ], true );\r
1650                                 };\r
1651                         };\r
1652 \r
1653                         if( !elm ) return;\r
1654                         that._listeners && X_EventDispatcher_toggleAllEvents( that, false );// イベントの退避\r
1655                         \r
1656                         // 破棄前にインタラクティブな属性値を控える\r
1657                         if( X_Node_Attr_HAS_VALUE[ that._tag ] && ( !that._newAttrs || !X_Object_inObject( 'value', that._newAttrs ) ) ){\r
1658                                 if( !that._attrs ) that._attrs = {};\r
1659                                 that._attrs.value = elm.value;\r
1660                         };\r
1661                         if( that._tag === 'OPTION' && ( !that._newAttrs || !X_Object_inObject( 'selected', that._newAttrs ) ) ){\r
1662                                 if( !that._attrs ) that._attrs = {};\r
1663                                 that._attrs.selected = elm.selected;\r
1664                         };\r
1665                         if( that._tag === 'SELECT' && ( !that._newAttrs || !X_Object_inObject( 'selectedIndex', that._newAttrs ) ) ){\r
1666                                 if( !that._attrs ) that._attrs = {};\r
1667                                 that._attrs.selectedIndex = elm.selectedIndex;\r
1668                         };\r
1669                         if( that._tag === 'INPUT' && that._attr && ( that._attr.type === 'checkbox' || that._attr.type === 'radio' ) && ( !that._newAttrs || !X_Object_inObject( 'checked', that._newAttrs ) ) ){\r
1670                                 if( !that._attrs ) that._attrs = {};\r
1671                                 that._attrs.checked = elm.checked;\r
1672                         };\r
1673 \r
1674                         elm.removeAttribute( 'id' ); // ?\r
1675                         //document.all[ that._id || ( 'ie4uid' + that._uid ) ] = null; // MacIE5 でエラー\r
1676                         if( !isChild ) elm.outerHTML = '';\r
1677                         delete that._rawObject;\r
1678                 }) :\r
1679                 (function(){});\r
1680 \r
1681 X_ViewPort.listenOnce( X.Event.UNLOAD, X_Node__actualRemove, [ X_Node_html, true ] );\r
1682 \r