OSDN Git Service

Version 0.6.7
[pettanr/clientJs.git] / 0.6.x / js / dom / 14_XDomNode.js
1 \r
2 /*\r
3  * Node( rawElement | rawTextnode | htmlString | textString )\r
4  */\r
5 ;(function( window, document, undeifned ){\r
6 X.Dom.Node = function( v ){\r
7         var nodeList, xnode, parent, uid;\r
8         \r
9         if( Node._newByTag ){\r
10                 delete Node._newByTag;\r
11                 this._tag      = v;\r
12                 this._nodeType = 1;\r
13         } else\r
14         if( Node._newByText ){\r
15                 delete Node._newByText;\r
16                 this._text     = v;\r
17                 this._nodeType = 3;\r
18         } else {\r
19                 if( 1 < arguments.length ){\r
20                         return new X.Dom.NodeList( arguments );\r
21                 };\r
22                 if( v && 1 < v.length && typeof v !== 'string' && v[ v.length - 1 ] ){\r
23                         return new X.Dom.NodeList( v );\r
24                 };\r
25 \r
26                 if( !this || this.append !== Node.prototype.append ) return new Node( v );\r
27 \r
28                 switch( Node._getType( v ) ){\r
29                         case Node.IS_XHNODE :\r
30                                 return v;\r
31                         case Node.IS_RAW_HTML :\r
32                                 if( xnode = Node._getXNode( v ) ) return xnode;\r
33                                 // dom2 || dom0\r
34                                 this.parent    = v !== document.body && ( parent = v.parentNode || v.parent ) && Node._getXNode( parent, v );\r
35                                 this._rawNode  = v;\r
36                                 this._nodeType = 1;\r
37                                 break;\r
38                         case Node.IS_RAW_TEXT :\r
39                                 if( xnode = Node._getXNode( v ) ) return xnode;\r
40                                 // v.parentNode && ( this.parent = Node._getXNode( v.parentNode ) );\r
41                                 this._rawNode  = v;\r
42                                 this._nodeType = 3;\r
43                                 break;\r
44                         case Node.IS_HTML_STRING :\r
45                         case Node.IS_STRING :\r
46                                 if( nodeList = X.Dom.parse( v, true ) && 1 < nodeList.length ) return new X.Dom.NodeList( nodeList );\r
47                                 if( nodeList.length ) return nodeList[ 0 ];\r
48                                 return Node._chashe[ 0 ];\r
49                         default :\r
50                                 if( Node._chashe.length ) return Node._chashe[ 0 ];\r
51                                 return;\r
52                 };              \r
53         };\r
54         \r
55         this._uid = Node._chashe.length;\r
56         Node._chashe[ this._uid ] = this;\r
57         \r
58         if( this._rawNode ){\r
59                 //alert( this._rawNode.tagName || this._rawNode.data );\r
60                 // this._nodeType === 1 && 4 < X.UA.IE && X.UA.IE < 5 ) ?\r
61                 //      this._rawNode.setAttribute( 'uid', '' + this._uid ) :\r
62                         this._nodeType === 1 && /*this._rawNode.setAttribute( 'uid', '' + this._uid ); //*/( this._rawNode.uid = this._uid );\r
63                 if( 9 < this._uid ) return;\r
64                 //alert( ( this._rawNode.tagName || this._rawNode.data ) + this._rawNode.uid );\r
65         };\r
66 };\r
67 \r
68 var Node = X.Dom.Node;\r
69 \r
70 Node._getType = function( v ){\r
71         if( v === '' ) return Node.IS_STRING;\r
72         if( !v ) return 0;\r
73         if( v.constructor === Node ) return Node.IS_XHNODE;\r
74         if( v.tagName ) return Node.IS_RAW_HTML;\r
75         if( v.nodeType === 3 ) return Node.IS_RAW_TEXT;\r
76         if( typeof v === 'string' ){\r
77                 return '<' === v.charAt( 0 ) && v.charAt( v.length - 1 ) === '>' ? Node.IS_HTML_STRING : Node.IS_STRING;\r
78         };\r
79         return 0;\r
80 };\r
81 Node.create = function( tag ){\r
82         Node._newByTag = true;\r
83         return new Node( tag );\r
84 };\r
85 Node.createText = function( text ){\r
86         Node._newByText = true;\r
87         return new Node( text );\r
88 };\r
89 \r
90 Node._chashe = [];\r
91 Node._chashe[ 0 ] = new Node();\r
92 Node._getXNode = function( node, v ){\r
93         if( !node ) return;\r
94         var uid;\r
95         if( X.UA.IE && X.UA.IE < 5 ){\r
96                 uid = parseFloat( node.getAttribute( 'uid' ) );\r
97                 return uid && Node._chashe[ uid ];\r
98         } else {\r
99                 return node.uid && Node._chashe[ node.uid ];\r
100         };\r
101 };\r
102 \r
103 Node.hasClass = function( elm , className ){\r
104         var cnames  = ( elm.className || '' ).split( ' ' ),\r
105                 _cnames = className.split( ' ' ),\r
106                 cname,\r
107                 i = _cnames.length;\r
108         for( ; i; ){\r
109                 cname = _cnames[ --i ];\r
110                 if( cname === '' ) continue;\r
111                 if( cnames.indexOf( cname ) === -1 ) return false;\r
112         };\r
113         return true;\r
114 };\r
115 \r
116 Node.IS_XHNODE      = 1;\r
117 Node.IS_RAW_HTML    = 2;\r
118 Node.IS_RAW_TEXT    = 3;\r
119 Node.IS_HTML_STRING = 4;\r
120 Node.IS_STRING      = 5;\r
121 \r
122 Node.prototype._uid       = 0;\r
123 Node.prototype._nodeType  = 0;\r
124 Node.prototype._rawNode   = null;\r
125 Node.prototype._tag       = null;\r
126 Node.prototype._text      = null;\r
127 Node.prototype._id        = null;\r
128 Node.prototype._className = null;\r
129 Node.prototype._attr      = null;\r
130 Node.prototype._children  = null;\r
131 Node.prototype._events    = null;\r
132 Node.prototype.parent     = null;\r
133 \r
134 /* --------------------------------------\r
135  *  Dom Level 2\r
136  */\r
137 if( document.getElementById ){\r
138         Node._dom2cleanUp = function( xnode ){\r
139                 var elm      = xnode._rawNode,\r
140                         children = xnode._children,\r
141                         childNodes, i, l, child, _child;\r
142                 if( elm && children && ( childNodes = elm.childNodes ) ){\r
143                         for( i = 0, l = children.length; i < l; ++i ){\r
144                                 child = children[ i ];\r
145                                 if( child.constractor === Node ) child = child._create( true );\r
146                                 if( typeof child === 'string'  ) child = document.createTextNode( child );\r
147                                 if( ( _child = childNodes[ i ] ) !== child ){\r
148                                         _child ?\r
149                                                 elm.insetBefore( child, _child ) :\r
150                                                 elm.appendChild( child );\r
151                                         _child && elm.removeChild( _child );\r
152                                 };\r
153                         };\r
154                         while( ( _child = childNodes[ i ] ) ){\r
155                                 elm.removeChild( _child );\r
156                         };\r
157                 };\r
158         };      \r
159 };\r
160 \r
161 /* --------------------------------------\r
162  *  Create\r
163  */\r
164 Node.prototype._create =\r
165         // document.createElement of ie4 is only for OPTION & IMAGE.\r
166         ( document.appendChild ) ? (function( isChild ){\r
167                 var tag = this._tag, node, frg;\r
168                 if( tag === 'input' ){\r
169                         // ie7 以下では createElement では name 等が働かない!\r
170                 };\r
171                 if( !( node = this._rawNode ) ){\r
172                         this._isNew = true;\r
173                         node = this._rawNode = ( tag ? document.createElement( tag ) : document.createTextNode( this._text ) );\r
174                 };\r
175                 // fragument がある場合 children も足して\r
176                 // Mozilla: 1.0+, IE: 6.0+, Netscape: 2.0+, Safari: 1.0+, Opera: 7.0+\r
177                 if( !isChild && document.createDocumentFragment ){\r
178                         if( node.nodeType === 1 ){\r
179                                 frg = document.createDocumentFragment();\r
180                                 frg.appendChild( node );\r
181                                 Node._dom2cleanUp( this );\r
182                                 return frg;\r
183                         };\r
184                 };\r
185                 return node;\r
186         }) :\r
187         document.all ? (function(){\r
188                 var elm, id, html, children, i, l, child;\r
189                 if( elm = this._ie4getRawNode() ){\r
190                         // 追加する前に要素を抜く\r
191                         this.remove();\r
192                         return elm.outerHTML;\r
193                 };\r
194                 // attr\r
195                 id       = this._id || this._ie4uid || ( 'ie4uid_' + ( ++Node.ie4uid ) );\r
196                 html     = [ '<', this._tag, id ? ( ' id="' + id + '"' ) : '', '>' ];\r
197                 if( ( children = this._children ) && ( l = children.length ) ){\r
198                         for( i = 0; i < l; ++i ){\r
199                                 child = children[ i ];\r
200                                 html[ html.length ] = child.constractor === Node ? child._create() : ( child.outerHTML || child );\r
201                         };\r
202                 };\r
203                 html[ html.length ] = '<\/' + this._tag + '>';\r
204                 return html.join( '' );\r
205         }) :\r
206         (function(){});\r
207 \r
208 Node.prototype._afterCreate =\r
209         ( document.appendChild ) ? (function( parent ){\r
210                 var _children = this._children,\r
211                         node      = this._rawNode,\r
212                         eChildren = node.childNodes,\r
213                         _child, i, l;\r
214                 this.parent = parent;\r
215                 if( this._isNew ){\r
216                         if( _children && !document.createDocumentFragment ){    \r
217                                 Node._dom2cleanUp( this ); // docFrg が使えない場合、doc 追加後に子を追加\r
218                         };\r
219                         node.uid = this._uid;\r
220                         // attr\r
221                         // イベントの復帰\r
222                         delete this._isNew;\r
223                 };\r
224                 /*\r
225                  * elm.childNodes を this._children にリンクさせる\r
226                  */\r
227                 if( _children ){\r
228                         for( i = 0, l = _children.length; i < l; ++i ){\r
229                                 _child = _children[ i ];\r
230                                 _child.constractor === Node ? _child._afterCreate( this ) : ( _children[ i ] = eChildren[ i ] );\r
231                         };\r
232                 } else\r
233                 if( eChildren && eChildren.length ){\r
234                         this._children = [];\r
235                         this._children.push.apply( this._children, eChildren );\r
236                 };\r
237                 return this;\r
238         }) :\r
239         document.all ? (function( parent ){\r
240                 var elm       = this._nodeType === 1 && this._ie4getRawNode(),\r
241                         _children = this._children,\r
242                         eChildren = elm && elm.innerHTML && Node._ie4getChildNodes( elm ),\r
243                         _child, i, l;\r
244                 this.parent = parent;\r
245                 /*\r
246                  * elm.children を this._children にリンクさせる\r
247                  */\r
248                 if( _children ){\r
249                         for( i = 0; i < l; ++i ){\r
250                                 _child = _children[ i ];\r
251                                 if( _child.constractor === Node ){\r
252                                         if( _child._ie4getRawNode() === eChildren[ i ] ){\r
253                                                 _child._afterCreate( this );\r
254                                         } else {\r
255                                                 alert( 'error XHTMLElement._afterCreate() _child._ie4getRawNode() === eChildren[ i ]' );\r
256                                         };\r
257                                 } else\r
258                                 if( _child !== eChildren[ i ] ){\r
259                                         alert( 'error XHTMLElement._afterCreate() _child !== eChildren[ i ]' );\r
260                                 };\r
261                         };\r
262                 } else\r
263                 if( eChildren ){\r
264                         this._children = eChildren;\r
265                 } else {\r
266 \r
267                 };\r
268                 /*\r
269                  * イベントの復帰 if( this._events && ( elm = this._ie4getRawNode() ) )\r
270                  */\r
271                 \r
272                 delete this._ie4dirty;\r
273                 delete this._ie4dirtyChildren;\r
274         }) :\r
275         (function(){});\r
276 \r
277 /* --------------------------------------\r
278  *  Create\r
279  */\r
280 Node.prototype.create = function( tag ){\r
281         var elm, xnode;\r
282         if( this._nodeType !== 1 ) return;\r
283         if( !this._children ) this._children = [];\r
284         \r
285         elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
286         \r
287         if( elm ){\r
288                 if( document.appendChild ){\r
289                         elm.appendChild( document.createElement( tag ) );\r
290                         xnode = new Node( elm.lastChild );\r
291                 } else\r
292                 if( document.all ){\r
293                         elm.insertAdjacentHTML( 'BeforeEnd', '<' + tag + '>' );\r
294                         xnode = new Node( elm.children[ elm.children.length - 1 ] );\r
295                 } else {\r
296                         \r
297                 };\r
298         } else {\r
299                 Node._newByTag = true;\r
300                 xnode = new Node( tag );\r
301         };\r
302         xnode.parent = this;\r
303         this._children[ this._children.length ] = xnode;\r
304         return xnode;\r
305 };\r
306 \r
307 /* --------------------------------------\r
308  *  CreateText\r
309  */\r
310 Node.prototype.createText = function( text ){\r
311         var elm, xnode;\r
312         if( this._nodeType !== 1 ) return;\r
313         if( !this._children ) this._children = [];\r
314         \r
315         elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
316         \r
317         if( elm ){\r
318                 if( document.createTextNode ){\r
319                         elm.appendChild( document.createTextNode( text ) );\r
320                         xnode = new Node( elm.lastChild );\r
321                 } else\r
322                 if( document.all ){\r
323                         elm.insertAdjacentHTML( 'BeforeEnd', text );\r
324                         Node._newByText = true;\r
325                         xnode = new Node( text );\r
326                 } else {\r
327                         \r
328                 };\r
329         } else {\r
330                 Node._newByText = true;\r
331                 xnode = new Node( text );\r
332         };\r
333         xnode.parent = this;\r
334         this._children[ this._children.length ] = xnode;\r
335         return xnode;\r
336 };\r
337 \r
338 /* --------------------------------------\r
339  *  Add\r
340  * Node\r
341  * HtmlElement の場合は内部使用専用 そのため event の破棄等しない\r
342  */\r
343 Node.prototype.append = function( v ){\r
344         var elm, i, l, children;\r
345         if( this._nodeType !== 1 ) return;\r
346         \r
347         if( 1 < arguments.length ){\r
348                 for( i = 0, l = arguments.length; i < l; ++i ){\r
349                         this.append( arguments[ i ] );\r
350                 };\r
351                 return this;\r
352         };\r
353         \r
354         if( !this._children ) this._children = [];\r
355         \r
356         elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
357         switch( Node._getType( v ) ){\r
358                 case Node.IS_RAW_HTML :\r
359                 case Node.IS_RAW_TEXT :\r
360                         if( elm ){\r
361                                 if( document.appendChild ){\r
362                                         elm.appendChild( v );\r
363                                 } else\r
364                                 if( document.all ){\r
365                                         elm.insertAdjacentHTML( 'BeforeEnd', v.outerHTML );\r
366                                         v = elm.children[ elm.children.length - 1 ];\r
367                                 } else {\r
368                                         \r
369                                 };\r
370                         };\r
371                         this._children[ this._children.length ] = v;\r
372                         break;\r
373                 case Node.IS_HTML_STRING :\r
374                 case Node.IS_STRING :\r
375                         v = X.Dom.parse( v, true );\r
376                         if( elm ){\r
377                                 for( i = 0, l = v.length; i < l; ++i ){\r
378                                         this.append( v[ i ] );\r
379                                 };\r
380                         } else\r
381                         if( v.length ){\r
382                                 this._children.push.apply( this._children, v );\r
383                         };\r
384                         break;\r
385                 case Node.IS_XHNODE :\r
386                         if( elm ){\r
387                                 if( document.appendChild ){\r
388                                         elm.appendChild( v._create() );\r
389                                         v._afterCreate( this );\r
390                                 } else\r
391                                 if( document.all ){\r
392                                         elm.insertAdjacentHTML( 'BeforeEnd', v._create() );\r
393                                         v._afterCreate( this );\r
394                                 } else {\r
395                                         \r
396                                 };\r
397                         };\r
398                         this._children[ this._children.length ] = v;\r
399         };\r
400         return this;\r
401 };\r
402 \r
403 \r
404 Node.prototype.appendAt = function( start, v ){\r
405         var l = arguments.length,\r
406                 children = this._children,\r
407                 node, i, prev, next;\r
408         if( this._nodeType !== 1 ) return;\r
409         \r
410         if( !children ) children = this._children = [];\r
411         \r
412         if( children.length <= start ){\r
413                 for( i = 1; i < l; ++i ){\r
414                         return this.append( arguments[ i ] );\r
415                 };\r
416                 return this;\r
417         };\r
418         if( start < 0 ) start = 0;\r
419         if( 2 < l ){\r
420                 for( ; l; ){\r
421                         this.appendAt( start, arguments[ --l ] );\r
422                 };\r
423                 return this;\r
424         };\r
425         if( this._nodeType !== 1 ) return this;\r
426         \r
427         if( !this.parent ){\r
428                 children.splice( start, 0, v );\r
429                 return this;\r
430         };\r
431         elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
432         switch( Node._getType( v ) ){\r
433                 case Node.IS_RAW_HTML :\r
434                 case Node.IS_RAW_TEXT :\r
435                         if( elm ){\r
436                                 if( document.appendChild ){\r
437                                         elm.insertBefore( v, elm.childNodes[ start ] );\r
438                                 } else\r
439                                 if( document.all ){\r
440                                         if( start === 0 ){\r
441                                                 elm.insertAdjacentHTML( 'AfterBegin', v.outerHTML );\r
442                                                 v = elm.children[ 0 ];\r
443                                         } else\r
444                                         if( ( next = children[ start ] ) && typeof next !== 'string' && next._nodeType !== 3 &&\r
445                                                 ( next = ( next._ie4getRawNode ? next._ie4getRawNode() : next ) ) ){\r
446                                                 next.insertAdjacentHTML( 'BeforeBegin', v.outerHTML );\r
447                                                 v = elm.children[ ( Array.prototype.indexOf.call( elm.children, next ) ) - 1 ];\r
448                                         } else\r
449                                         if( 0 < start && ( prev = children[ start - 1 ] ) && typeof prev !== 'string' && prev._nodeType !== 3 &&\r
450                                                 ( prev = ( prev._ie4getRawNode ? prev._ie4getRawNode() : prev ) ) ){\r
451                                                 prev.insertAdjacentHTML( 'AfterEnd', v.outerHTML );\r
452                                                 v = elm.children[ ( Array.prototype.indexOf.call( elm.children, prev ) ) + 1 ];\r
453                                         } else {\r
454                                                 this._ie4reserveUpdate( v );// テキストノードの間に入れる場合!\r
455                                         };\r
456                                 } else {\r
457                                         \r
458                                 };\r
459                                 children.splice( start, 0, v );\r
460                         } else {\r
461                                 children.splice( start, 0, v );\r
462                         };\r
463                         break;\r
464                 case Node.IS_HTML_STRING :\r
465                 case Node.IS_STRING :\r
466                         v = X.Dom.parse( v, true );\r
467                         if( elm ){\r
468                                 for( i = v.length; i; ){\r
469                                         this.appendAt( start, v[ --i ] );\r
470                                 };\r
471                         } else\r
472                         if( v.length ){\r
473                                 children.push.apply( children, v );\r
474                         };\r
475                         break;\r
476                 case Node.IS_XHNODE :\r
477                         if( elm ){\r
478                                 if( document.appendChild ){\r
479                                         elm.insertBefore( v._create(), elm.childNodes[ start ] );\r
480                                         v._afterCreate( this );\r
481                                 } else\r
482                                 if( document.all ){\r
483                                         this._ie4reserveUpdate( v );\r
484                                 } else {\r
485                                         \r
486                                 };\r
487                         };\r
488                         children.splice( start, 0, v );\r
489         };\r
490         return this;\r
491 };\r
492 \r
493 Node.prototype.appendTo = function( parent, opt_start ){\r
494         !opt_start ? new Node( parent ).append( this ) : new Node( parent ).appendAt( opt_start, this );\r
495 };\r
496 \r
497 Node.prototype.appendToRoot = function( opt_start ){\r
498         !opt_start ? Node.root.append( this ) : Node.root.appendAt( opt_start, this );\r
499 };\r
500 \r
501 /* --------------------------------------\r
502  *  Before , After\r
503  */\r
504 Node.prototype.before = function( v ){\r
505         \r
506 };\r
507 \r
508 Node.prototype.after = function( v ){\r
509         \r
510 };\r
511 \r
512 /* --------------------------------------\r
513  *  Remove\r
514  */\r
515 Node.prototype.remove = function(){\r
516         var parent = this.parent;\r
517                 \r
518         if( !parent ) return this;\r
519         if( document.removeChild ){\r
520                 this._rawNode && parent._rawNode.removeChild( this._rawNode );\r
521         } else\r
522         if( document.all ){\r
523                 this._ie4beforeRemove();\r
524                 delete this._ie4dirty;\r
525                 delete this._ie4dirtyChildren;\r
526                 parent._ie4reserveUpdate();\r
527         } else {\r
528                 \r
529         };\r
530 \r
531         parent._children.splice( parent._children.indexOf( v ), 1 );\r
532         delete this.parent;\r
533         return this;\r
534 };\r
535 \r
536 Node.prototype.empty = function( v ){\r
537         \r
538 };\r
539 \r
540 /* --------------------------------------\r
541  *  replace\r
542  */\r
543 \r
544 /* --------------------------------------\r
545  *  destory\r
546  */\r
547 Node.prototype.destroy = function( v ){\r
548         \r
549 };\r
550 \r
551 /* --------------------------------------\r
552  *  for ie4\r
553  */\r
554 if( !document.getElementById && document.all ){\r
555         Node.prototype._ie4beforeRemove = function(){\r
556                 var children = this._children,\r
557                         child, i, l, elm;\r
558                 if( children ){\r
559                         for( i = 0, l = children.length; i < l; ++i ){\r
560                                 child = children[ i ];\r
561                                 child.constractor === Node && child._ie4beforeRemove();\r
562                         };      \r
563                 };\r
564                 if( elm = this._ie4getRawNode() ){\r
565                         // イベントの削除\r
566                         if( elm.id && elm.id !== this._ie4uid ){\r
567                                 this._id = elm.id;\r
568                         } else\r
569                         if( !elm.id ){\r
570                                 this._ie4uid = elm.id = 'ie4uid_' + ( ++Node.ie4uid );\r
571                         };\r
572                         this._htmlText = elm.outerHTML;\r
573                         delete this._rawNode;\r
574                 };\r
575         };\r
576         \r
577         Node.prototype._ie4getRawNode = function(){\r
578                 var elm, uid;\r
579                 if( ( elm = this._rawNode ) && elm.parentElement ) return elm;\r
580                 if( ( uid = this._id ) && ( elm = document.all[ uid ] ) ){\r
581                         return ( this._rawNode = elm );\r
582                 };\r
583                 if( ( uid = this._ie4uid ) && ( elm = document.all[ uid ] ) ){\r
584                         delete this._ie4uid;\r
585                         delete this._htmlText;\r
586                         if( this._id ) elm.id = this._id;\r
587                         return ( this._rawNode = elm );\r
588                 };\r
589         };\r
590         \r
591         Node.ie4uid = 0;\r
592         \r
593         Node.prototype._ie4reserveUpdate = function( child ){\r
594                 var root = Node.root;\r
595                 child && ( child._ie4dirty = true );\r
596                 this._ie4dirtyChildren = true;\r
597                 if( root._reserved === true ) return;\r
598                 root._reserved = true;\r
599                 X.Timer.once( 1, root, root._ie4startUpdate );\r
600         };\r
601         \r
602         Node.prototype._ie4startUpdate = function(){\r
603                 if( this._reserved !== true ) return;\r
604                 //if( this._ie4getRawNode() ) this._rawNode = document.all.tags( 'BODY' )[ 0 ];\r
605                 // !this._rawNode && onload(  )\r
606                 delete this._reserved;\r
607                 if( !this._children ) return;\r
608                 this._ie4commitUpdate()._ie4afterUpdate();\r
609         };\r
610         \r
611         Node.prototype._ie4commitUpdate = function(){\r
612                 var children = this._children,\r
613                         i, l, child, html;\r
614                 if( !this._ie4dirtyChildren && !this._ie4dirty ){\r
615                         for( i = 0, l = children.length; i < l; ++i ){\r
616                                 child = children[ i ];\r
617                                 child.constractor === Node && child._ie4commitUpdate();\r
618                         };\r
619                         return this;\r
620                 };\r
621                 html = [];\r
622                 for( i = 0, l = children.length; i < l; ++i ){\r
623                         child = children[ i ];\r
624                         html[ html.length ] = child.constractor === Node ?\r
625                                 ( child._ie4dirty ? child._ie4commitUpdate() : child._create() ) :\r
626                                 ( child.outerHTML || child );\r
627                 };\r
628                 if( !this._ie4dirty ){\r
629                         this._rawNode.innerHTML = html.join( '' );\r
630                         return this;\r
631                 };\r
632                 return html.join( '' );\r
633         };\r
634         \r
635         Node.prototype._ie4afterUpdate = function(){\r
636                 var children = this._children,\r
637                         i, l, child;\r
638                 if( !this._ie4dirtyChildren && !this._ie4dirty ){\r
639                         for( i = 0, l = children.length; i < l; ++i ){\r
640                                 child = children[ i ];\r
641                                 child.constractor === Node && child._ie4afterUpdate();\r
642                         };\r
643                 };\r
644 \r
645                 for( i = 0, l = children.length; i < l; ++i ){\r
646                         child = children[ i ];\r
647                         child.constractor === Node &&\r
648                                 ( child._ie4dirty ? child._ie4afterUpdate() : child._afterCreate( this ) );\r
649                 };\r
650                 delete this._ie4dirtyChildren;\r
651                 delete this._ie4dirty;\r
652         };\r
653         \r
654         /*\r
655          * ie4 に TextNode は存在しない。       よって、Element.children にテキストノードは無視される。\r
656          * そこでテキストノードを判定して控える操作が必要になる。\r
657          * elm と string( TextNode の変わり ) の混在する配列が返る\r
658          * return [ elm, 'text', elm, elm, ...  ]\r
659          */\r
660         Node._ie4getChildNodes = function( elm ){\r
661                 var html     = elm.innerHTML,\r
662                         children = elm.children,\r
663                         l        = children.length,\r
664                         _        = '',\r
665                         cr, i, j, child, outer, index, nodes;\r
666                 if( l < 1 ){\r
667                         if( html.length ) return [ html ]; // new X.TextNode( html );\r
668                         return [];\r
669                 };\r
670                 cr    = Node._ie4getCRCChars( html );\r
671                 nodes = [];\r
672                 j     = -1;\r
673                 html = html.split( cr ).join( _ );\r
674                 for( i = 0; i <= l; ++i ){\r
675                         child = children[ i ];\r
676                         outer = child.outerHTML.split( cr ).join( _ );\r
677                         index = html.indexOf( outer );\r
678                         if( index === -1 ){\r
679                                 alert( 'Node._ie4getChildNodes\n' + outer + '\n' + html.substr( 0, 100 ) );\r
680                                 continue;\r
681                         };\r
682                         if( 0 < index ) nodes[ ++j ] = html.substr( 0, index ); // new X.TextNode( html );\r
683                         nodes[ ++j ] = child; // Element\r
684                         html = html.substr( index + outer.length );\r
685                 };\r
686                 if( html.length ) nodes[ ++j ] = html; // new X.TextNode( html );\r
687                 return nodes;\r
688         };\r
689         Node._ie4getCRCChars = function( src ){\r
690                 return 0 <= src.indexOf( '\r\n' ) ? '\r\n' :\r
691                         0 <= src.indexOf( '\n' ) ? '\n' :\r
692                         0 <= src.indexOf( '\r' ) ? '\r' : '\n';\r
693         };\r
694 };\r
695 \r
696 /* --------------------------------------\r
697  *  contains\r
698  */\r
699 Node.prototype.contains = function( v ){\r
700         var node, _node;\r
701         if( !this.parent || this._nodeType !== -1 ) return false;\r
702         node = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
703         switch( Node._getType( v ) ){\r
704                 case Node.IS_RAW_HTML :\r
705                 case Node.IS_RAW_TEXT :\r
706                         return node.contains( v );\r
707                 case Node.IS_XHNODE :\r
708                         _node = v._ie4getRawNode ? v._ie4getRawNode() : v._rawNode;\r
709                         if( _node ) return node.contains( _node );\r
710                 default :\r
711                         return false;\r
712         };\r
713         if( this._children.indexOf( v ) !== -1 ) return true;\r
714         for( i = 0, l = this._children.length; i < l; ++i ){\r
715                 if( ( new Node( this._children[ i ] ) ).contains( v ) === true ) return true\r
716         };\r
717         return false;\r
718 };\r
719 \r
720 /* --------------------------------------\r
721  *  getChild\r
722  */\r
723 Node.prototype.getChildAt = function( index ){\r
724         var children = this._children,\r
725                 elm, childNodes, child, xnode;\r
726         if( this._nodeType !== 1 || index < 0 ) return;\r
727         if( !children ){\r
728                 elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
729                 if( !elm ){\r
730                         if( v === 0 && this.text ){\r
731                                 children = this._children = [ this.text ];\r
732                         } else {\r
733                                 return;\r
734                         };\r
735                 } else {\r
736                         /* DOM level2 */\r
737                         if( childNodes = elm.childNodes ){\r
738                                 children = this._children = [];\r
739                                 children.push.apply( children, childNodes );\r
740                         } else\r
741                         /* ie4 DOM */\r
742                         if( elm.innerHTML ){\r
743                                 children = this._children = Node._ie4getChildNodes( elm );\r
744                         } else {\r
745                                 return;\r
746                         };\r
747                 };\r
748         };\r
749         if( children.length <= index ) return;\r
750         child = children[ index ];\r
751         if( child.constractor === Node ) return child;\r
752         xnode = new Node( child );\r
753         xnode.parent = this;\r
754         return children[ index ] = xnode;\r
755 };\r
756 /* --------------------------------------\r
757  *  getByID\r
758  */\r
759 /* --------------------------------------\r
760  *  getByTag\r
761  */\r
762 Node.prototype.getByTag = function( tag ){\r
763         var parent = this.parent, elm, tags;\r
764         if( !parent || this._nodeType !== -1 ) return;\r
765         if( document.getElementsByTagName ){\r
766                 if( !( elm = this._rawNode ) ) return;\r
767                 new X.Dom.NodeList( elm.getElementsByTagName( tag ) );\r
768         } else\r
769         if( document.all ){\r
770                 if( !( elm = this._ie4getRawNode() ) ) return;\r
771                 Node.root._reserved === true && Node.root._ie4startUpdate();\r
772                 new X.Dom.NodeList( elm.all.tags( tag ) );      \r
773         } else {\r
774                 \r
775         };\r
776 };\r
777 \r
778 /* --------------------------------------\r
779  *  getByClass\r
780  */\r
781 Node.prototype.getByClass =\r
782                 document.getElementsByClassName ?\r
783                         (function( className ){\r
784                                 var parent = this.parent, elm;\r
785                                 if( !parent ) return;\r
786                                 if( !( elm = this._rawNode ) || elm.nodeType !== 1 ) return;\r
787                                 return new X.Dom.NodeList( elm.getElementsByClassName( className ) );\r
788                         }) :\r
789                 document.getElementsByTagName ?\r
790                         (function( className ){\r
791                                 var parent = this.parent, elm;\r
792                                 var live  = parent.getElementsByTagName( '*' ),\r
793                                         nodes = [],\r
794                     node, i;\r
795                 for( i = live.length; i; ){\r
796                         nodes[ --i ] = live[ i ];\r
797                 };\r
798                                 for( i = nodes.length; i; ){\r
799                                         node = nodes[ --i ];\r
800                                         ( node.nodeType !== 1 || !node.className || !node.className.length || Node.hasClass( node, className ) === false ) && nodes.splice( i, 1 );\r
801                                 };\r
802                                 return new X.Dom.NodeList( nodes );\r
803                         }) :\r
804                 document.all ?\r
805                         (function( parent, className ){\r
806                                 var live  = parent.all,\r
807                                         nodes = [],\r
808                     node, i;\r
809                 for( i = live.length; i; ){\r
810                         nodes[ --i ] = live[ i ];\r
811                 };\r
812                                 for( i = nodes.length; i; ){\r
813                                         node = nodes[ --i ];\r
814                                         ( !node.className || !node.className.length || Node.hasClass( node, className ) === false ) && nodes.splice( i, 1 );\r
815                                 };\r
816                                 return new X.Dom.NodeList( nodes );\r
817                         }) :\r
818                         (function(){}),\r
819 \r
820 // listen, unlisten, listening\r
821 \r
822 /* --------------------------------------\r
823  *  prevNode, nextNode, firstChild, lastChild\r
824  */\r
825 \r
826 Node.prototype.prevNode = function(){\r
827         var parent = this.parent, index;\r
828         if( !parent ) return;\r
829         index = parent.children.indexOf( this );\r
830         if( 0 < index ) new Node( parent.children[ index - 1 ] );\r
831 };\r
832 Node.prototype.nextNode = function(){\r
833         var parent = this.parent, children, index;\r
834         if( !parent ) return;\r
835         children = parent.children;\r
836         index    = children.indexOf( this );\r
837         if( index < children.length ) new Node( children[ index + 1 ] );\r
838 };\r
839 Node.prototype.firstChild = function(){\r
840         return this.getChildAt( 0 );\r
841 };\r
842 Node.prototype.lastChild = function(){\r
843         return this.getChildAt( this._children.length - 1 );\r
844 };\r
845 \r
846 /* --------------------------------------\r
847  *  getOrder\r
848  */\r
849 Node.prototype.getOrder = function(){\r
850         var parent = this.parent;\r
851         if( !parent ) return -1;\r
852         return parent.children.indexOf( this );\r
853 };\r
854 \r
855 /* --------------------------------------\r
856  *  className, cssText, cssObject\r
857  */\r
858 \r
859 \r
860 /* --------------------------------------\r
861  *  attribute\r
862  */\r
863 Node.prototype.attr = function(){\r
864 };\r
865 \r
866 /* --------------------------------------\r
867  *  Width, Height\r
868  */\r
869 Node.prototype.width = function(){\r
870         var parent = this.parent, elm;\r
871         if( !parent ) return 0;\r
872         if( document.getElementById ){\r
873                 return ( elm = this._rawNode ) ? elm.offsetWidth : 0;\r
874         } else\r
875         if( document.all ){\r
876                 if( !( elm = this._ie4getRawNode() ) ) return 0;\r
877                 Node.root._reserved === true && Node.root._ie4startUpdate();\r
878                 return elm.offsetWidth;         \r
879         } else {\r
880                 \r
881         };\r
882 };\r
883 \r
884 Node.prototype.height = function(){\r
885         var parent = this.parent, elm;\r
886         if( !parent ) return 0;\r
887         if( document.getElementById ){\r
888                 return ( elm = this._rawNode ) ? elm.offsetHeight : 0;\r
889         } else\r
890         if( document.all ){\r
891                 if( !( elm = this._ie4getRawNode() ) ) return 0;\r
892                 Node.root._reserved === true && Node.root._ie4startUpdate();\r
893                 return elm.offsetHeight;                \r
894         } else {\r
895                 \r
896         };\r
897 };\r
898 \r
899 /* --------------------------------------\r
900  *  Content Width, Content Height\r
901  */\r
902 \r
903 \r
904 \r
905 X.Dom.Event.add( window, 'load', function(){\r
906         var r   = Node.root = new Node( document.body ),\r
907                 elm = r._rawNode,\r
908                 createTree;\r
909         r.appendTo = r.appendToRoot = r.before = r.after = r.clone = r.remove = r.destroy = r.prevNode = r.nextNode = new Function( 'return this' );\r
910         \r
911         if( elm.childNodes ){\r
912                 createTree = function( xnode, elm, children ){\r
913                         var i = 0,\r
914                                 l = children.length,\r
915                                 child, _xnode;\r
916                         for( ; i < l; ++i ){\r
917                                 child = children[ i ];\r
918                                 if( child.nodeType === 1 ){\r
919                                         if( !xnode._children ) xnode._children = [];\r
920                                         xnode._children[ xnode._children.length ] = _xnode = new Node( child );\r
921                                         _xnode.parent = xnode;\r
922                                         child.childNodes.length && createTree( _xnode, child, child.childNodes );\r
923                                 } else\r
924                                 if( child.nodeType === 3 ){\r
925                                         if( !xnode._children ) xnode._children = [];\r
926                                         xnode._children[ xnode._children.length ] = new Node( child );\r
927                                 } else {\r
928                                         elm.removeChild( child );\r
929                                         --i;\r
930                                         --l;\r
931                                 };\r
932                         };\r
933                 };\r
934                 createTree( r, elm, elm.childNodes );\r
935         } else\r
936         if( elm.children ){\r
937                 createTree = function( xnode, children ){\r
938                         var i = 0,\r
939                                 l = children.length,\r
940                                 j = 0, child, _xnode;\r
941                         \r
942                         var nodes = [];\r
943                         for( ; i < xnode._children.length; ++i ){\r
944                                 child = xnode._children[ i ];\r
945                                 nodes.push( child._tag || child._text );\r
946                         };\r
947                         i = 0;\r
948                         for( ; i < l; ++i ){\r
949                                 child = children[ i ];\r
950                                 alert( xnode._rawNode.tagName + '[' + nodes.join( ', ' ) + '] > "' + child.tagName + '" ' + j + '/' + xnode._children.length )\r
951                                 while( j < xnode._children.length ){\r
952                                         _xnode = xnode._children[ j ];\r
953                                         ++j;\r
954                                         if( _xnode._nodeType === 1 ){\r
955                                                 _xnode._rawNode = child;\r
956                                                 _xnode.parent   = xnode;\r
957                                                 //alert( _xnode._tag + ' <= ' + child.tagName );\r
958                                                 child.children.length && createTree( _xnode, child.children );\r
959                                                 break;\r
960                                         };\r
961                                 };\r
962                         };\r
963                 };\r
964                 r._children = [];\r
965                 nodes = X.Dom.parse( elm.innerHTML, true );\r
966                 for( i = nodes.length; i; ){\r
967                         r._children[ --i ] = nodes[ i ];\r
968                         alert( nodes[ i ]._tag || nodes[ i ]._text )\r
969                 };\r
970                 createTree( r, elm.children );\r
971                 delete r._reserved;\r
972         } else {\r
973                 \r
974         };\r
975         \r
976         return X.Callback.UN_LISTEN;\r
977 } );\r
978 \r
979 })( window, document );