2 X.Dom._useBuilder = true;
\r
4 /* --------------------------------------
\r
5 * 通常のwebページに対して使用する場合、dom ready で dom tree を写し取るために使う.
\r
6 * 完全にワンページアプリで<body/>が空な場合、このコードはビルドに含める必要はない
\r
8 X.Dom.listenOnce( X.Dom.Event.DOM_PRE_INIT,
\r
9 document.getElementById ?
\r
16 (function( elm, skip, head ){
\r
17 var me = arguments.callee,
\r
18 moveToHead = 'style,bgsound,area,base,meta'.split( ',' ),
\r
19 remove = 'script,noscript,noframes,comment,!,noembed,nolayer'.split( ',' ),
\r
20 noncleanup = 'pre,textarea,code,kbd,samp,xmp,plaintext,listing'.split( ',' ),
\r
21 nodes = X.copyArray( elm.childNodes ),
\r
24 node, tag, textNode, content;
\r
25 for( ; i < l; ++i ){
\r
27 switch( node.nodeType ){
\r
29 tag = node.tagName.toLowerCase();
\r
30 if( moveToHead.indexOf( tag ) !== -1 ){
\r
31 head = head || document.getElementsByTagName( 'head' )[ 0 ];
\r
32 head.appendChild( node );
\r
35 if( remove.indexOf( tag ) !== -1 ){
\r
36 elm.removeChild( node );
\r
39 // pre タグ以下はスペースの置換は行わない
\r
40 node.childNodes && node.childNodes.length && me( node, skip || noncleanup.indexOf( tag ) !== -1, head );
\r
45 content = skip ? node.data : X.Dom.cleanupWhiteSpace( node.data );
\r
46 //console.log( 'Delete space ' + node.data.length + ' => ' + content.length );
\r
47 if( !textNode && content !== ' ' && content.length ){
\r
48 node.data = content;
\r
53 textNode.data += content; // 直前が TextNode の場合 一本化して削除
\r
55 // ブロック要素直下のスペースだけは削除??
\r
57 //console.log( 'Remove type: ' + node.nodeType + ' value: ' + node.nodeValue );
\r
58 elm.removeChild( node );
\r
64 function createTree( xnode, childNodes, skipCleanup, textarea ){
\r
67 l = childNodes.length,
\r
68 child, _xnode, f, tag, text, _xtext, doc;
\r
69 childNodes = X.copyArray( childNodes );
\r
72 xnode.attr( 'value', xnode.html() ).empty();
\r
76 for( ; i < l; ++i ){
\r
77 child = childNodes[ i ];
\r
78 tag = child.tagName;
\r
79 if( ( child.nodeType !== 1 && child.nodeType !== 3 ) || tag === '!' || ( tag && tag.charAt( 0 ) === '/' ) ){
\r
80 child.parentNode.removeChild( child );
\r
84 while( xnode._xnodes && j < xnode._xnodes.length ){
\r
85 _xnode = xnode._xnodes[ j ];
\r
86 _xnode.parent = xnode;
\r
88 if( _xnode._xnodeType === 1 ){
\r
89 if( child.nodeType !== 1 ){
\r
90 if( !( text = child.data ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
\r
91 child.parentNode.removeChild( child );
\r
94 alert( '[' +xnode._tag + '>' +_xnode._tag + '] !== ' + child.nodeType + '\n' + child.data );
\r
98 if( _xnode._tag.toUpperCase() !== tag ){
\r
99 alert( '[' +xnode._tag + '>' +_xnode._tag + ' ' + (_xnode._xnodes ? _xnode._xnodes.length : '' ) + '] !== ' + tag + ' ' + (child.childNodes ? child.childNodes.length : '' ) + '\n' + child.outerHTML );
\r
103 _xnode._rawNode = child;
\r
104 //if( ( doc = child.ownerDocument || child.document ) && ( doc.createElement( 'p' ).tagName === doc.createElement( 'P' ).tagName ) ){
\r
105 if( tag.charAt( 0 ) === '/' ) tag = tag.slice( 1 );
\r
106 _xnode._tag = tag; // .toUpperCase()
\r
108 _xnode._root = xnode._root;
\r
109 child.UID = _xnode._uid;
\r
110 if( 0 <= X.Dom.cleanupTagNames.indexOf( tag.toLowerCase() ) || tag === 'SCRIPT' ){ // ie で body 内の script が2度よばれるのに対処
\r
111 //alert( '[' +xnode._tag + '>' + _xnode._tag + '] remove ... ' );
\r
116 //alert( '[' +xnode._tag + '>' + _xnode._tag + ' ' + (_xnode._xnodes ? _xnode._xnodes.length : '' ) + '] === ' + tag + ' ' + (child.childNodes ? child.childNodes.length : '' ) + ' Hit\n' + child.outerHTML );
\r
117 child.childNodes && child.childNodes.length && createTree( _xnode, child.childNodes, skipCleanup || 0 <= X.Dom.skipCleanupTagNames.indexOf( tag.toLowerCase() ), tag === 'TEXTAREA' );
\r
125 if( _xnode._xnodeType === 3 ){
\r
127 if( child.nodeType !== 3 ){
\r
128 if( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
\r
129 console.log( '[' +xnode._tag + '>' + _xnode._uid + '] destroy ... ' );
\r
134 alert( xnode._tag + '>' + '"' + _xnode._text + '" !== ' + tag + '\n' + child.outerHTML );
\r
139 _xnode._rawNode = child;
\r
140 _xnode._root = xnode._root;
\r
141 if( !skipCleanup ){
\r
142 if( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
\r
143 console.log( '[' +xnode._tag + '>' + _xnode._uid + '] destroy ... ' );
\r
149 _xtext.text( _xtext._text + text );
\r
150 console.log( '[' +xnode._tag + '>' + _xnode._uid + '] xtext,destroy ... ' );
\r
155 //alert( xnode._tag + '>' + '"' + text + '"\n' + child.data );
\r
156 _xnode.text( text );
\r
160 _xtext.text( _xtext._text + _xnode.text );
\r
161 console.log( '[' +xnode._tag + '>' + _xnode._uid + '] xtext,destroy ... ' );
\r
166 _xtext = _xtext || _xnode;
\r
170 alert( 'no hit!' );
\r
175 //if( !f ) alert( '**** ' + child.outerHTML );
\r
177 while( xnode._xnodes && j < xnode._xnodes.length ){
\r
178 _xnode = xnode._xnodes[ j ];
\r
179 _xnode.parent = xnode;
\r
188 X.Dom.asyncParse( body.innerHTML, true )
\r
189 .listenOnce( X.Event.SUCCESS, X.Dom._onAsyncParseComplete, [ createTree ] );
\r
190 //.listen( X.Event.PROGRESS, function(e){alert(e.progress);} );
\r
196 i, n = 0, parser, elmProgress = '_xdom_builder_progress';
\r
198 function createTree( xnode, children, skipCleanup, textarea ){
\r
199 var parent = xnode,
\r
200 xnodes = X.copyArray( parent._xnodes ),
\r
201 l = xnodes && xnodes.length,
\r
202 m = children.length,
\r
203 i = 0, j = 0, flag = 0,
\r
204 elm, tag, xtext, text;
\r
205 //children = X.copyArray( children );
\r
208 xnode.attr( 'value', xnode.html() ).empty();
\r
212 for( ; i < xnodes.length; ++i ){
\r
213 xnode = xnodes[ i ];
\r
214 xnode.parent = parent;
\r
216 if( xnode._xnodeType === 3 ){
\r
217 //alert( X.Dom.cleanupWhiteSpace( xnode._text ) );
\r
218 if( !skipCleanup ){
\r
219 if( !( text = xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
\r
223 //alert( 'xtext ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
224 xtext.text( xtext._text + text );
\r
227 //alert( 'xnode ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
228 xnode.text( text );
\r
232 //alert( 'skip ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
233 xtext.text( xtext._text + xnode._text );
\r
237 xtext = xtext || xnode;
\r
241 if( xnode._xnodeType !== 1 ){
\r
242 //alert( xnode._xnodeType )
\r
246 for( ; j < m; ++j ){
\r
247 elm = children[ j ];
\r
250 * 未知のタグについては、閉じタグも含めてタグ名扱いになる
\r
252 if( tag === '!' || tag.charAt( 0 ) === '/' ){
\r
253 //alert( '## ' + tag );
\r
256 if( xnode._tag !== tag ){
\r
257 alert( xnode._tag + ' ' + ' !== ' + tag + '\nxnode.html():' + xnode.attr('cite') + '\nelm.outerHTML:' + elm.outerHTML );
\r
259 xnode._rawNode = elm;
\r
260 xnode._root = parent._root;
\r
261 //xnode._tag = X.Dom.DTD.TAG_FIX[ tag ] || tag;
\r
262 if( 0 <= X.Dom.cleanupTagNames.indexOf( tag.toLowerCase() ) || tag === 'SCRIPT' ){
\r
266 xnode._xnodes && xnode._xnodes.length && createTree( xnode, elm.children, skipCleanup || 0 <= X.Dom.skipCleanupTagNames.indexOf( tag.toLowerCase() ), tag === 'TEXTAREA' );
\r
268 !xnode._id && elm.setAttribute( 'id', 'ie4uid' + xnode._uid );
\r
269 elm.setAttribute( 'UID', xnode._uid );
\r
271 tag === 'INPUT' && (
\r
273 ( xnode._attrs = { type : 'text' } ) :
\r
274 !xnode._attrs.type || ( xnode._attrs.type = 'text' )
\r
283 if( !xnode._rawNode ){
\r
284 alert( xnode._tag + ' ' + xnode._id + ' !== none...' );
\r
290 ( flag & 6 ) && ( parent._dirty |= X.Dom.Dirty.IE4_TEXTNODE_FIX );
\r
293 * http://support.microsoft.com/kb/812417/ja
\r
294 * PRB: outerHTML の HTML 要素のプロパティは、既定の属性は表示されません。
\r
296 * body.innerHTML でなく、 body.outerHTML にはできなかった、、、
\r
298 body.insertAdjacentHTML( 'BeforeEnd', '<div id="' + elmProgress + '" style="position:absolute;top:0;left:0;z-index:9999;width:0;height:0.5em;background:#00f;overflow:hidden;"></div>' );
\r
299 elmProgress = document.all[ elmProgress ];
\r
301 parser = X.Dom.asyncParse( body.innerHTML, true )
\r
302 .listenOnce( X.Event.SUCCESS, X.Dom._onAsyncParseComplete, [ createTree ] )
\r
303 .listen( X.Event.PROGRESS,
\r
305 elmProgress.style.width = ( e.progress * 100 | 0 ) + '%';
\r
313 X.Dom._onAsyncParseComplete = function( e, createTree ){
\r
314 var xnodes = Node.root._xnodes = [], t;
\r
315 xnodes.push.apply( xnodes, e.xnodes );
\r
318 createTree( Node.root, document.body.childNodes || document.body.children );
\r
319 //alert( X.getTime() - t );
\r
321 X.Dom.asyncDispatch( 0, { type : X.Dom.Event.DOM_BUILDER_COMPLETE } );
\r
323 delete X.Dom._onAsyncParseComplete;
\r
327 function asyncCreateTree( parent, elems, xnodeProgress, async ){
\r
328 var xnodes = async ? 0 : X.copyArray( parent._xnodes ),
\r
329 l = async ? 0 : xnodes.length,
\r
330 current = async ? async.current : { xnodes : xnodes, l : l, i : 0 },
\r
331 stack = async ? async.stack : [],
\r
332 count = async ? async.count : 0,
\r
333 startTime = X.getTime(),
\r
334 xnodes, xnode, l, progress;
\r
335 while( current || ( current = stack.pop() ) ){
\r
336 for( ; current.i < current.l; ++current.i ){
\r
337 xnode = current.xnoeds[ current.i ];
\r
343 if(( xnodes = xnode._xnodes ) && ( l = xnodes.length ) ){
\r
345 stack[ stack.length ] = current;
\r
347 xnodes : X.copyArray( xnodes ),
\r
354 if( startTime + 16 <= X.getTime() ){
\r
356 async.current = ++current.i < current.l && current;
\r
357 async.count = count;
\r
359 X.Timer.once( 0, asyncCreateTree, [ null, xnodeProgress, async || { stack : stack, current : ++current.i < current.l && current, count : count } ] );
\r
361 progress = 1 - count / Node._chashe.length;
\r
368 X.Dom.asyncDispatch( 0, { type : X.Dom.Event.DOM_BUILDER_COMPLETE } );
\r