2 X.Dom._useBuilder = true;
\r
4 X.Dom._isCleanupTarget = function( elm ){
\r
5 var cname = ' ' + elm.className + ' ',
\r
6 tag = ( elm.tagName || '' ).toUpperCase();
\r
7 return cname.indexOf( ' skip-cleanup ' ) === -1 &&
\r
8 ( X.Dom.cleanupTagNames[ tag ] || 0 < cname.indexOf( ' cleanup-target ' ) );
\r
11 X.Dom._o7_remove = function( node ){
\r
12 var parent = node.parentNode;
\r
13 if( node.nodeType === 1 || node.nodeType === 3 ){
\r
14 parent && parent.removeChild( node );
\r
20 /* --------------------------------------
\r
21 * 通常のwebページに対して使用する場合、dom ready で dom tree を写し取るために使う.
\r
22 * 完全にワンページアプリで<body/>が空な場合、このコードはビルドに含める必要はない
\r
24 * TODO (注4) IE6 の空白に関する“癖”について
\r
25 * http://kojs.sukobuto.com/docs/visible-binding
\r
26 * IE6 には、「空の span エレメントに続く空白は無視される」という謎な癖があります。
\r
28 X.Dom.listenOnce( X.Dom.Event.DOM_PRE_INIT,
\r
37 // textarea の内容を控えて、消す。xnode tree 構築後に復帰。でないと、html パースでこける
\r
40 X.UA.MacIE || (function/*cleanUpTree*/( elm, skip, head ){
\r
41 var nodes = X.copyArray( elm.childNodes ),
\r
44 node, tag, textNode, content;
\r
45 for( ; i < l; ++i ){
\r
47 switch( node.nodeType ){
\r
49 tag = node.tagName.toUpperCase();
\r
50 if( X.Dom.moveToHead[ tag ] ){
\r
51 head = head || document.getElementsByTagName( 'head' )[ 0 ];
\r
52 head.appendChild( node );
\r
55 if( X.Dom.cleanupTagNames[ tag ] ){
\r
56 elm.removeChild( node );
\r
59 // pre タグ以下はスペースの置換は行わない
\r
60 node.childNodes && node.childNodes.length && /*cleanUpTree*/arguments.callee( node, skip || X.Dom.skipCleanupTagNames[ tag ], head );
\r
65 content = skip ? node.data : X.Dom.cleanupWhiteSpace( node.data );
\r
66 //console.log( 'Delete space ' + node.data.length + ' => ' + content.length );
\r
67 if( !textNode && content !== ' ' && content.length ){
\r
68 node.data = content;
\r
73 textNode.data += content; // 直前が TextNode の場合 一本化して削除
\r
75 // ブロック要素直下のスペースだけは削除??
\r
77 //console.log( 'Remove type: ' + node.nodeType + ' value: ' + node.nodeValue );
\r
79 elm.removeChild( node );
\r
81 X.Dom._o7_remove( node );
\r
89 html = body.innerHTML;
\r
91 body.appendChild( elmProgress = document.createElement( 'div' ) );
\r
92 elmProgress.style.cssText = 'position:absolute;top:0;left:0;z-index:9999;width:0;height:0.5em;background:#00f;overflow:hidden;';
\r
93 elmProgress.setAttribute( 'style', 'position:absolute;top:0;left:0;z-index:9999;width:0;height:0.5em;background:#00f;overflow:hidden;' );
\r
95 X.Dom.asyncParse( html, true )
\r
96 .listen( X.Event.PROGRESS,
\r
98 elmProgress.style.width = ( e.progress * 100 | 0 ) + '%';
\r
101 .listenOnce( X.Event.SUCCESS, function( e ){
\r
102 var xnodes = Node.root._xnodes = [], t;
\r
103 xnodes.push.apply( xnodes, e.xnodes );
\r
104 elmProgress.style.width = '100%';
\r
106 X.Dom._asyncCreateTree( Node.root, body.childNodes, elmProgress );
\r
114 elmProgress = '_xdom_builder_progress',
\r
118 * http://support.microsoft.com/kb/812417/ja
\r
119 * PRB: outerHTML の HTML 要素のプロパティは、既定の属性は表示されません。
\r
121 * body.innerHTML でなく、 body.outerHTML にはできなかった、、、
\r
123 html = body.innerHTML;
\r
124 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
125 elmProgress = document.all[ elmProgress ];
\r
127 X.Dom.asyncParse( html, true )
\r
128 .listen( X.Event.PROGRESS,
\r
130 elmProgress.style.width = ( e.progress * 100 | 0 ) + '%';
\r
133 .listenOnce( X.Event.SUCCESS,
\r
135 var xnodes = Node.root._xnodes = [], t;
\r
136 xnodes.push.apply( xnodes, e.xnodes );
\r
137 elmProgress.style.width = '100%';
\r
139 X.Dom._asyncCreateTree( Node.root, body.childNodes || body.children, elmProgress );
\r
147 X.Dom._asyncCreateTree = function ( parent, elems, elmProgress, async ){
\r
148 var xnodes = async ? 0 : X.copyArray( parent._xnodes ),
\r
149 l = async ? 0 : xnodes.length,
\r
150 stack = async ? async.stack : [],
\r
151 done = async ? async.done : 0,
\r
152 startTime = X.getTime(),
\r
153 current = async ? async.current : {
\r
158 elems : X.copyArray( elems ),
\r
164 //alert( 'X.Dom._asyncCreateTree' );
\r
165 while( current || ( current = stack.pop() ) ){
\r
169 parent = current.me;
\r
170 xnodes = current.xnodes;
\r
171 while( xnode = xnodes[ i ] ){
\r
173 dive = X.Dom._bindElementToXnode( parent, xnode, current );
\r
179 stack[ stack.length ] = current;
\r
185 xnodes = dive.xnodes;
\r
189 if( startTime + 16 <= X.getTime() ){
\r
192 async.current = i < l && current;
\r
195 //alert( 'koko?' );
\r
196 X.Timer.once( 0, X.Dom._asyncCreateTree, [ null, null, elmProgress, async || { stack : stack, current : i < l && current, done : done } ] );
\r
198 elmProgress.style.width = ( ( 1 - done / Node._chashe.length ) * 100 | 0 ) + '%';
\r
206 X.Dom.asyncDispatch( 0, { type : X.Dom.Event.DOM_BUILDER_COMPLETE } );
\r
207 elmProgress.parentNode ? elmProgress.parentNode.removeChild( elmProgress ) : ( elmProgress.outerHTML = '' );
\r
208 delete X.Dom._asyncCreateTree;
\r
209 delete X.Dom._bindElementToXnode;
\r
212 X.Dom._bindElementToXnode =
\r
214 (function( parent, xnode, current ){
\r
215 var elems = current.elems,
\r
218 xtext = current.xtext,
\r
219 skipCleanup = current.skipCleanup,
\r
220 inPreTag = current.inPreTag,
\r
223 xnode.parent = parent;
\r
225 for( ; current.j < m; ++current.j ){
\r
226 elm = elems[ current.j ];
\r
227 tag = elm.tagName && elm.tagName.toUpperCase();
\r
228 if( ( elm.nodeType !== 1 && elm.nodeType !== 3 ) || tag === '!' || ( tag && tag.charAt( 0 ) === '/' ) ){
\r
229 if( !X.UA.Opera7 ){
\r
230 elm.parentNode.removeChild( elm );
\r
232 X.Dom._o7_remove( elm );
\r
237 if( xnode._xnodeType === 1 ){
\r
238 if( elm.nodeType === 3 ){
\r
239 if( !( text = elm.data ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
\r
240 //alert( text.charCodeAt( 0 ) );
\r
241 if( !X.UA.Opera7 ){
\r
242 elm.parentNode.removeChild( elm );
\r
244 X.Dom._o7_remove( elm );
\r
248 alert( '1:[' +parent._tag + '>' +xnode._tag + '] !== ' + elm.nodeType + '\n' + ( elm.data ) );
\r
250 if( xnode._tag !== tag ){
\r
251 alert( '2:[' +parent._tag + '>' +xnode._tag + ' len:' + (xnode._xnodes ? xnode._xnodes.length : '' ) + '] !== ' + tag + ' ' + (elm.childNodes ? elm.childNodes.length : '' ) + '\n' + elm.outerHTML );
\r
253 xnode._rawNode = elm;
\r
254 //if( ( doc = elm.ownerDocument || elm.document ) && ( doc.createElement( 'p' ).tagName === doc.createElement( 'P' ).tagName ) ){
\r
255 if( tag.charAt( 0 ) === '/' ) tag = tag.slice( 1 );
\r
258 xnode._root = parent._root;
\r
259 elm.UID = xnode._uid;
\r
261 if( tag === 'TEXTAREA' ){
\r
262 xnode.attr( 'value', xnode.html() ).empty();
\r
263 current.xtext = null;
\r
265 if( !xnode.hasClass( 'skip-cleanup' ) && ( X.Dom.cleanupTagNames[ tag ] || xnode.hasClass( 'cleanup-target' ) ) ){ // ie で body 内の script が2度よばれるのに対処
\r
266 //alert( '[' +parent._tag + '>' + xnode._tag + '] remove ... ' );
\r
269 if( elm.childNodes && elm.childNodes.length ){
\r
270 //alert( '[' +parent._tag + '>' + xnode._tag + ' ' + (xnode._xnodes ? xnode._xnodes.length : '' ) + '] === ' + tag + ' ' + (elm.childNodes ? elm.childNodes.length : '' ) + ' Hit\n' + elm.outerHTML );
\r
271 current.xtext = null;
\r
276 xnodes : X.copyArray( xnode._xnodes ),
\r
280 l : xnode._xnodes.length,
\r
281 elems : X.copyArray( elm.childNodes ),
\r
283 skipCleanup : skipCleanup || X.Dom.skipCleanupTagNames[ tag ]
\r
291 if( elm.nodeType !== 3 ){
\r
292 if( !( text = xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
\r
293 console.log( '[' +parent._tag + '>' + xnode._uid + '] destroy ... ' );
\r
297 alert( parent._tag + ' > ' + '"' + xnode._text + '" !== ' + tag + '\n' +
\r
298 'prev : ' + ( xnode.prevNode() && xnode.prevNode().html() ) + '\n' +
\r
299 'next : ' + ( xnode.nextNode() && xnode.nextNode().html() ) + '\n' +
\r
300 'html : ' + elm.outerHTML );
\r
305 xnode._rawNode = elm;
\r
306 xnode._root = parent._root;
\r
307 if( !skipCleanup ){
\r
308 if( !( text = xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
\r
309 console.log( '[' +parent._tag + '>' + xnode._uid + '] destroy ... ' );
\r
313 xtext.text( xtext._text + text );
\r
314 console.log( '[' +parent._tag + '>' + xnode._uid + '] xtext,destroy ... ' );
\r
317 //alert( parent._tag + '>' + '"' + text + '"\n' + elm.data );
\r
318 xnode.text( text );
\r
322 xtext.text( xtext._text + xnode._text );
\r
323 console.log( '[' +parent._tag + '>' + xnode._uid + '] xtext,destroy ... ' );
\r
326 current.xtext = xtext || xnode;
\r
330 (function ( parent, xnode, current ){
\r
331 var elems = current.elems,
\r
334 xtext = current.xtext,
\r
335 skipCleanup = current.skipCleanup,
\r
338 xnode.parent = parent;
\r
340 if( xnode._xnodeType === 3 ){
\r
341 //alert( X.Dom.cleanupWhiteSpace( xnode._text ) );
\r
342 if( !skipCleanup ){
\r
343 if( !( text = xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
\r
347 //alert( 'xtext ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
348 xtext.text( xtext._text + text );
\r
351 //alert( 'xnode ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
352 xnode.text( text );
\r
356 //alert( 'skip ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
357 xtext.text( xtext._text + xnode._text );
\r
361 current.xtext = xtext || xnode;
\r
365 if( xnode._xnodeType !== 1 ){
\r
366 //alert( xnode._xnodeType )
\r
370 for( ; j < m; ++j, ++current.j ){
\r
374 * 未知のタグについては、閉じタグも含めてタグ名扱いになる
\r
376 if( tag === '!' || tag.charAt( 0 ) === '/' ){
\r
377 //alert( '## ' + tag );
\r
380 if( xnode._tag !== tag ){
\r
381 alert( xnode._tag + ' ' + ' !== ' + tag + '\nxnode.html():' + xnode.attr('cite') + '\nelm.outerHTML:' + elm.outerHTML );
\r
385 xnode._rawNode = elm;
\r
386 xnode._root = parent._root;
\r
387 //xnode._tag = X.Dom.DTD.TAG_FIX[ tag ] || tag;
\r
388 if( !xnode.hasClass( 'skip-cleanup' ) && ( X.Dom.cleanupTagNames[ tag ] || xnode.hasClass( 'cleanup-target' ) ) ){
\r
393 !xnode._id && elm.setAttribute( 'id', 'ie4uid' + xnode._uid );
\r
394 elm.setAttribute( 'UID', xnode._uid );
\r
396 tag === 'INPUT' && (
\r
398 ( xnode._attrs = { type : 'text' } ) :
\r
399 xnode._attrs.type || ( xnode._attrs.type = 'text' )
\r
402 current.xtext = null;
\r
404 if( tag === 'TEXTAREA' ){
\r
405 xnode.attr( 'value', xnode.html() ).empty();
\r
407 if( xnode._xnodes && xnode._xnodes.length ){
\r
410 xnodes : X.copyArray( xnode._xnodes ),
\r
414 l : xnode._xnodes.length,
\r
415 elems : X.copyArray( elm.children ),
\r
417 skipCleanup : skipCleanup || X.Dom.skipCleanupTagNames[ tag ]
\r
424 if( !xnode._rawNode ){
\r
425 alert( xnode._tag + ' ' + xnode._id + ' !== none...' );
\r
429 ( current.flag & 6 ) && ( parent._dirty |= X.Dom.Dirty.IE4_TEXTNODE_FIX );
\r