OSDN Git Service

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