2 X_TEMP.X_Dom_useBuilder = true;
\r
4 X_TEMP._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_DTD_CLEANUP_TAGS[ tag ] || cname.indexOf( ' cleanup-target ' ) !== -1 );
\r
11 if( X_UA[ 'MacIE' ] ){
\r
13 X_TEMP._fixed_remove = function( node, xnode ){
\r
14 var parent = node.parentNode, l;
\r
16 node.nodeType !== 3 && alert( node.nodeType + '\n' + ( node.outerHTML || node.data ) );
\r
17 if( node.nodeType === 1 ){
\r
18 //node.outerHTML = '';
\r
19 parent && parent.removeChild( node );
\r
21 if( node.nodeType === 3 ){
\r
23 l = X_TEMP._removalTextNodes.length;
\r
25 //!l && X_Timer_once( 0, X_TEMP._timerRemove );
\r
26 //X_TEMP._removalTextNodes[ l ] = node;
\r
29 // str[str.length] = p;
\r
31 //alert( str.join( ',' ) + parent.innerHTML );
\r
32 //node.nodeValue = '';
\r
33 //parent.replaceChild( document.createElement( 'span' ), node );
\r
35 //var f = document.createDocumentFragment();
\r
36 //f.appendChild( e = document.createElement( 'span' ) );
\r
37 //f.replaceChild( node, e );
\r
38 //e.appendChild( f );
\r
39 //parent.appendChild( e = document.createElement( 'span' ) );
\r
40 //e.appendChild( node );
\r
41 //parent.removeChild( e );
\r
42 //node.parentNode = null;
\r
43 //document.body.appendChild( node );
\r
44 //parent.replaceChild( document.createComment( '' ), node );
\r
45 document.body.appendChild( node );
\r
47 if( parent.parentNode !== document.body ){
\r
48 var clone = parent.cloneNode( true );
\r
49 for( var i = 0, l = parent.childNodes.length; i < l; ++i ){
\r
50 if( parent.childNodes[ i ] !== node ){
\r
51 clone.removeChild( clone.childNodes[ i ] );
\r
54 //parent.parentNode.insertBefore( clone, parent );
\r
55 //parent.parentNode.removeChild( parent );
\r
56 parent.parentNode.insertBefore( clone, parent );
\r
57 parent.style.display = 'none';
\r
59 xnode.parent.parent[ '_rawObject' ] = clone;
\r
66 //if( !node.ownerDocument ) alert( 'no owner' );
\r
72 X_TEMP._removalTextNodes = [];
\r
74 X_TEMP._timerRemove = function(){
\r
75 var nodes = X_TEMP._removalTextNodes,
\r
77 while( i < 5 && nodes.length ){
\r
78 node = nodes.shift();
\r
79 if( node.parentNode ){
\r
80 //node.parentNode.removeChild( node );
\r
85 //nodes.length && X_Timer_once( 1000, X_TEMP._timerRemove );
\r
89 if( X_UA[ 'Opera7' ] ){
\r
91 X_TEMP._fixed_remove = function( node ){
\r
92 if( node.nodeType === 1 || node.nodeType === 3 ){
\r
93 node.parentNode && node.parentNode.removeChild( node );
\r
100 /* --------------------------------------
\r
101 * 通常のwebページに対して使用する場合、dom ready で dom tree を写し取るために使う.
\r
102 * 完全にワンページアプリで<body/>が空な場合、このコードはビルドに含める必要はない
\r
104 * TODO (注4) IE6 の空白に関する“癖”について
\r
105 * http://kojs.sukobuto.com/docs/visible-binding
\r
106 * IE6 には、「空の span エレメントに続く空白は無視される」という謎な癖があります。
\r
108 X_ViewPort[ 'listenOnce' ]( X_EVENT_PRE_INIT,
\r
111 var r = X_Node_body,
\r
112 body = r[ '_rawObject' ],
\r
113 copy, i, l, node, html,
\r
116 if( !X_TEMP.X_Dom_useBuilder ) return;
\r
118 X_HTMLParser_skipFixNesting = true;
\r
121 // textarea の内容を控えて、消す。xnode tree 構築後に復帰。でないと、html パースでこける
\r
122 //X_UA[ 'MacIE' ] && alert( body.innerHTML );
\r
124 (function/*cleanUpTree*/( elm, skip, head ){
\r
125 var nodes = X_Object_cloneArray( elm.childNodes ),
\r
128 node, tag, textNode, content;
\r
129 for( ; i < l; ++i ){
\r
131 switch( node.nodeType ){
\r
133 tag = node.tagName.toUpperCase();
\r
134 if( X_Dom_DTD_MOVE_TO_HEAD[ tag ] ){
\r
135 head = head || document.getElementsByTagName( 'head' )[ 0 ];
\r
136 head.appendChild( node );
\r
139 if( X_TEMP._isCleanupTarget( node ) ){
\r
140 elm.removeChild( node );
\r
143 // pre タグ以下はスペースの置換は行わない
\r
144 node.childNodes && node.childNodes.length && /*cleanUpTree*/arguments.callee( node, skip || X_Dom_DTD_SKIP_CLEANUP_TAGS[ tag ], head );
\r
149 content = skip ? node.data : X_String_cleanupWhiteSpace( node.data );
\r
150 //console.log( 'Delete space ' + node.data.length + ' => ' + content.length );
\r
151 if( !textNode && content !== ' ' && content.length ){
\r
152 node.data = content;
\r
157 textNode.data += content; // 直前が TextNode の場合 一本化して削除
\r
159 // ブロック要素直下のスペースだけは削除??
\r
161 //console.log( 'Remove type: ' + node.nodeType + ' value: ' + node.nodeValue );
\r
162 if( !X_UA[ 'Opera7' ] /*&& !X_UA[ 'MacIE' ] */ ){
\r
163 elm.removeChild( node );
\r
165 X_TEMP._fixed_remove( node );
\r
170 })( X_UA[ 'MacIE' ] ? ( copy = body.cloneNode( true ) ) : body );
\r
172 if( X_UA[ 'MacIE' ] ){
\r
173 document.write( html = copy.innerHTML );
\r
176 if( X_UA[ 'IE' ] <= 8 ){
\r
177 html = body.innerHTML.split( X_String_CRLF ).join( '' ); // 不要な改行が入る
\r
179 html = body.innerHTML;
\r
182 // Nokia s60 Safari
\r
183 if( html === 'fastinnerhtml!' ){
\r
185 for( i = 0, l = body.childNodes.length; i < l; ++i ){
\r
186 node = body.childNodes[ i ];
\r
187 html += ( node.outerHTML || node.data );
\r
192 body.appendChild( elmProgress = document.createElement( 'div' ) );
\r
193 elmProgress.style.cssText = 'position:absolute;top:0;left:0;z-index:9999;width:0;height:0.5em;background:#00f;overflow:hidden;';
\r
194 elmProgress.setAttribute( 'style', 'position:absolute;top:0;left:0;z-index:9999;width:0;height:0.5em;background:#00f;overflow:hidden;' );
\r
196 X_HTMLParser_asyncParse( html, true )
\r
197 [ 'listen' ]( X_EVENT_PROGRESS,
\r
199 elmProgress.style.width = ( e[ 'percent' ] * 100 | 0 ) + '%';
\r
202 [ 'listenOnce' ]( X_EVENT_SUCCESS,
\r
204 var xnodes = X_Node_body[ '_xnodes' ] = [], t;
\r
205 xnodes.push.apply( xnodes, e.xnodes );
\r
206 elmProgress.style.width = '100%';
\r
208 X_TEMP.asyncCreateTree( X_Node_body, body.childNodes, elmProgress );
\r
215 var r = X_Node_body,
\r
216 body = r[ '_rawObject' ],
\r
217 elmProgress = '_xdom_builder_progress',
\r
220 if( !X_TEMP.X_Dom_useBuilder ) return;
\r
223 * http://support.microsoft.com/kb/812417/ja
\r
224 * PRB: outerHTML の HTML 要素のプロパティは、既定の属性は表示されません。
\r
226 * body.innerHTML でなく、 body.outerHTML にはできなかった、、、
\r
228 html = body.innerHTML;
\r
229 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
230 elmProgress = document.all[ elmProgress ];
\r
232 X_HTMLParser_asyncParse( html, true )
\r
233 [ 'listen' ]( X_EVENT_PROGRESS,
\r
235 elmProgress.style.width = ( e.percent * 100 | 0 ) + '%';
\r
238 [ 'listenOnce' ]( X_EVENT_SUCCESS,
\r
240 var xnodes = X_Node_body[ '_xnodes' ] = [], t;
\r
241 xnodes.push.apply( xnodes, e.xnodes );
\r
242 elmProgress.style.width = '100%';
\r
244 X_TEMP.asyncCreateTree( X_Node_body, body.childNodes || body.children, elmProgress );
\r
252 X_TEMP.asyncCreateTree = function( parent, elems, elmProgress, async ){
\r
253 var xnodes = async ? 0 : X_Object_cloneArray( parent[ '_xnodes' ] ),
\r
254 l = async ? 0 : xnodes.length,
\r
255 stack = async ? async.stack : [],
\r
256 done = async ? async.done : 0,
\r
257 startTime = X_Timer_now(),
\r
258 current = async ? async.current : {
\r
263 elems : X_Object_cloneArray( elems ),
\r
269 //alert( 'X_TEMP.asyncCreateTree' );
\r
270 while( current || ( current = stack.pop() ) ){
\r
274 parent = current.me;
\r
275 xnodes = current.xnodes;
\r
276 while( xnode = xnodes[ i ] ){
\r
278 dive = X_TEMP.bindElementToXnode( parent, xnode, current );
\r
284 stack[ stack.length ] = current;
\r
290 xnodes = dive.xnodes;
\r
294 if( startTime + 16 <= X_Timer_now() ){
\r
297 async.current = i < l && current;
\r
300 //alert( 'koko?' );
\r
301 X_Timer_once( 0, X_TEMP.asyncCreateTree, [ null, null, elmProgress, async || { stack : stack, current : i < l && current, done : done } ] );
\r
303 elmProgress.style.width = ( ( 1 - done / X_Node_CHASHE.length ) * 100 | 0 ) + '%';
\r
311 console.log( 'xtree 作成完了' );
\r
312 X_ViewPort[ 'asyncDispatch' ]( X_EVENT_XTREE_READY );
\r
313 elmProgress.parentNode ? elmProgress.parentNode.removeChild( elmProgress ) : ( elmProgress.outerHTML = '' );
\r
314 delete X_TEMP.asyncCreateTree;
\r
315 delete X_TEMP.bindElementToXnode;
\r
316 delete X_TEMP.X_Dom_useBuilder;
\r
317 delete X_TEMP._isCleanupTarget;
\r
319 X_HTMLParser_skipFixNesting = false;
\r
322 X_TEMP.bindElementToXnode =
\r
324 (function( parent, xnode, current ){
\r
325 var elems = current.elems,
\r
328 xtext = current.xtext,
\r
329 skipCleanup = current.skipCleanup,
\r
330 inPreTag = current.inPreTag,
\r
333 xnode.parent = parent;
\r
335 for( ; current.j < m; ++current.j ){
\r
336 elm = elems[ current.j ];
\r
337 tag = elm.tagName && elm.tagName.toUpperCase();
\r
338 if( ( elm.nodeType !== 1 && elm.nodeType !== 3 ) || tag === '!' || ( tag && tag.charAt( 0 ) === '/' ) ){
\r
339 if( !X_UA[ 'Opera7' ] && !X_UA[ 'MacIE' ] ){
\r
340 elm.parentNode.removeChild( elm );
\r
342 X_TEMP._fixed_remove( elm );
\r
347 if( xnode[ '_tag' ] ){
\r
348 if( elm.nodeType === 3 ){
\r
349 if( !( text = elm.data ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
350 //alert( text.charCodeAt( 0 ) );
\r
351 if( !X_UA[ 'Opera7' ] && !X_UA[ 'MacIE' ] ){
\r
352 elm.parentNode.removeChild( elm );
\r
354 X_TEMP._fixed_remove( elm );
\r
358 alert( '1:[' +parent[ '_tag' ] + '>' +xnode[ '_tag' ] + '] !== ' + elm.nodeType + '\n' + ( elm.data ) );
\r
360 if( X_Dom_DTD_MOVE_TO_HEAD[ tag ] ){
\r
364 if( xnode[ '_tag' ] !== tag ){
\r
365 alert( '2:[' +parent[ '_tag' ] + '>' +xnode[ '_tag' ] + ' len:' + (xnode[ '_xnodes' ] ? xnode[ '_xnodes' ].length : '' ) + '] !== ' + tag + ' ' + (elm.childNodes ? elm.childNodes.length : '' ) + '\n' + elm.outerHTML );
\r
367 xnode[ '_rawObject' ] = elm;
\r
368 //if( ( doc = elm.ownerDocument || elm.document ) && ( doc.createElement( 'p' ).tagName === doc.createElement( 'P' ).tagName ) ){
\r
369 if( tag.charAt( 0 ) === '/' ) tag = tag.slice( 1 );
\r
370 xnode[ '_tag' ] = tag;
\r
372 xnode[ '_flags' ] |= X_NodeFlags_IN_TREE;
\r
373 xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
\r
374 elm[ 'UID' ] = xnode[ '_uid' ];
\r
375 current.xtext = null;
\r
377 if( tag === 'TEXTAREA' ){
\r
378 xnode[ 'attr' ]( 'value', xnode[ 'html' ]() )[ 'empty' ]();
\r
381 if( elm.childNodes && elm.childNodes.length ){
\r
382 //alert( '[' +parent[ '_tag' ] + '>' + xnode[ '_tag' ] + ' ' + (xnode[ '_xnodes' ] ? xnode[ '_xnodes' ].length : '' ) + '] === ' + tag + ' ' + (elm.childNodes ? elm.childNodes.length : '' ) + ' Hit\n' + elm.outerHTML );
\r
383 //current.xtext = null;
\r
388 xnodes : X_Object_cloneArray( xnode[ '_xnodes' ] ),
\r
392 l : xnode[ '_xnodes' ].length,
\r
393 elems : X_Object_cloneArray( elm.childNodes ),
\r
395 skipCleanup : skipCleanup || X_Dom_DTD_SKIP_CLEANUP_TAGS[ tag ]
\r
399 //current.xtext = null;
\r
405 if( elm.nodeType !== 3 ){
\r
406 if( !( text = xnode[ '_text' ] ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
407 console.log( '[' +parent[ '_tag' ] + '> UID:' + xnode[ '_uid' ] + ' len:' + xnode[ '_text' ].length + ' code : ' + xnode[ '_text' ].charCodeAt( 0 ) + ',' + xnode[ '_text' ].charCodeAt( 1 ) + '] destroyed.' );
\r
411 alert( parent[ '_tag' ] + ' > ' + '"' + xnode[ '_text' ] + '" !== ' + tag + '\n' +
\r
412 'prev : ' + ( xnode[ 'prev' ]() && xnode[ 'prev' ]()[ 'html' ]() ) + '\n' +
\r
413 'next : ' + ( xnode[ 'next' ]() && xnode[ 'next' ]()[ 'html' ]() ) + '\n' +
\r
414 'html : ' + elm.outerHTML );
\r
419 xnode[ '_rawObject' ] = elm;
\r
420 xnode[ '_flags' ] |= X_NodeFlags_IN_TREE;
\r
421 xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
\r
422 xnode[ '_text' ] = elm.data; // 正確
\r
424 if( !skipCleanup ){
\r
425 if( !( text = xnode[ '_text' ] ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
426 console.log( '[' +parent[ '_tag' ] + '>' + xnode[ '_uid' ] + '] destroy ... ' );
\r
430 xtext[ 'text' ]( xtext[ '_text' ] + text );
\r
431 console.log( '[' +parent[ '_tag' ] + '>' + xnode[ '_uid' ] + '] xtext,destroy ... ' );
\r
434 //alert( parent[ '_tag' ] + '>' + '"' + text + '"\n' + elm.data );
\r
435 xnode[ 'text' ]( text );
\r
439 xtext[ 'text' ]( xtext[ '_text' ] + xnode[ '_text' ] );
\r
440 console.log( '[' +parent[ '_tag' ] + '>' + xnode[ '_uid' ] + '] xtext,destroy ... ' );
\r
443 current.xtext = xtext || xnode;
\r
447 (function ( parent, xnode, current ){
\r
448 var elems = current.elems,
\r
451 xtext = current.xtext,
\r
452 skipCleanup = current.skipCleanup,
\r
455 xnode.parent = parent;
\r
457 if( !xnode[ '_tag' ] ){
\r
458 xnode[ '_flags' ] |= X_NodeFlags_IN_TREE;
\r
459 xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
\r
460 //alert( X_String_cleanupWhiteSpace( xnode[ '_text' ] ) );
\r
461 if( !skipCleanup ){
\r
462 if( !( text = xnode[ '_text' ] ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
467 //alert( 'xtext ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
468 xtext[ 'text' ]( xtext[ '_text' ] + text );
\r
471 //alert( 'xnode ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
472 xnode[ 'text' ]( text );
\r
476 //alert( 'skip ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
477 xtext[ 'text' ]( xtext[ '_text' ] + xnode[ '_text' ] );
\r
481 current.xtext = xtext || xnode;
\r
482 parent[ '_flags' ] |= X_NodeFlags_IE4_HAS_TEXTNODE;
\r
486 for( ; j < m; ++j, ++current.j ){
\r
490 * 未知のタグについては、閉じタグも含めてタグ名扱いになる
\r
492 if( tag === '!' || tag.charAt( 0 ) === '/' ){
\r
493 //alert( '## ' + tag );
\r
496 if( xnode[ '_tag' ] !== tag ){
\r
497 alert( xnode[ '_tag' ] + ' ' + ' !== ' + tag + '\nxnode.html():' + xnode.attr('cite') + '\nelm.outerHTML:' + elm.outerHTML );
\r
501 xnode[ '_rawObject' ] = elm;
\r
502 xnode[ '_flags' ] |= X_NodeFlags_IN_TREE;
\r
503 xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
\r
504 //xnode[ '_tag' ] = X_Dom_DTD_TAG_FIX[ tag ] || tag;
\r
505 if( X_TEMP._isCleanupTarget( elm ) ){ //!xnode[ 'hasClass' ]( 'skip-cleanup' ) && ( X_Dom_DTD_CLEANUP_TAGS[ tag ] || xnode[ 'hasClass' ]( 'cleanup-target' ) ) ){
\r
510 !xnode[ '_id' ] && elm.setAttribute( 'id', 'ie4uid' + xnode[ '_uid' ] );
\r
511 elm.setAttribute( 'UID', xnode[ '_uid' ] );
\r
513 tag === 'INPUT' && (
\r
514 !xnode[ '_attrs' ] ?
\r
515 ( xnode[ '_attrs' ] = { type : 'text' } ) :
\r
516 xnode[ '_attrs' ].type || ( xnode[ '_attrs' ].type = 'text' )
\r
518 parent[ '_flags' ] |= X_NodeFlags_IE4_HAS_ELEMENT;
\r
519 current.xtext = null;
\r
521 if( tag === 'TEXTAREA' ){
\r
522 xnode[ 'attr' ]( 'value', xnode[ 'html' ]() )[ 'empty' ]();
\r
524 if( xnode[ '_xnodes' ] && xnode[ '_xnodes' ].length ){
\r
527 xnodes : X_Object_cloneArray( xnode[ '_xnodes' ] ),
\r
531 l : xnode[ '_xnodes' ].length,
\r
532 elems : X_Object_cloneArray( elm.children ),
\r
534 skipCleanup : skipCleanup || X_Dom_DTD_SKIP_CLEANUP_TAGS[ tag ]
\r
541 if( !xnode[ '_rawObject' ] ){
\r
542 alert( xnode[ '_tag' ] + ' ' + xnode[ '_id' ] + ' !== none...' );
\r
546 console.log( 'X.Dom.Builder' );
\r
547 console.log( 'bootTime : ' + ( X_Timer_now() - X.bootTime ) );