OSDN Git Service

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