OSDN Git Service

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