OSDN Git Service

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