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
26 !l && X_Timer_once( 0, X_TEMP._timerRemove );
\r
27 X_TEMP._removalTextNodes[ l ] = node;
\r
30 str[str.length] = p;
\r
32 alert( str.join( ',' ) + parent.innerHTML );
\r
33 node.nodeValue = '';
\r
34 parent.replaceChild( document.createElement( 'span' ), node );
\r
36 var f = document.createDocumentFragment();
\r
37 f.appendChild( e = document.createElement( 'span' ) );
\r
38 f.replaceChild( node, e );
\r
40 parent.appendChild( e = document.createElement( 'span' ) );
\r
41 e.appendChild( node );
\r
42 parent.removeChild( e );
\r
43 node.parentNode = null;
\r
44 X_elmBody.appendChild( node );
\r
45 parent.replaceChild( document.createComment( '' ), node ); */
\r
46 X_elmBody.appendChild( node );
\r
49 if( parent.parentNode !== X_elmBody ){
\r
50 var clone = parent.cloneNode( true );
\r
51 for( var i = 0, l = parent.childNodes.length; i < l; ++i ){
\r
52 if( parent.childNodes[ i ] !== node ){
\r
53 clone.removeChild( clone.childNodes[ i ] );
\r
56 //parent.parentNode.insertBefore( clone, parent );
\r
57 //parent.parentNode.removeChild( parent );
\r
58 parent.parentNode.insertBefore( clone, parent );
\r
59 parent.style.display = 'none';
\r
61 xnode.parent.parent[ '_rawObject' ] = clone;
\r
68 //if( !node.ownerDocument ) alert( 'no owner' );
\r
74 X_TEMP._removalTextNodes = [];
\r
76 X_TEMP._timerRemove = function(){
\r
77 var nodes = X_TEMP._removalTextNodes,
\r
79 while( i < 5 && nodes.length ){
\r
80 node = nodes.shift();
\r
81 if( node.parentNode ){
\r
82 //node.parentNode.removeChild( node );
\r
87 //nodes.length && X_Timer_once( 1000, X_TEMP._timerRemove );
\r
91 if( X_UA[ 'Opera7' ] ){
\r
93 X_TEMP._fixed_remove = function( node ){
\r
94 if( node.nodeType === 1 || node.nodeType === 3 ){
\r
95 node.parentNode && node.parentNode.removeChild( node );
\r
102 /* --------------------------------------
\r
103 * 通常のwebページに対して使用する場合、dom ready で dom tree を写し取るために使う.
\r
104 * 完全にワンページアプリで<body/>が空な場合、このコードはビルドに含める必要はない
\r
106 * TODO (注4) IE6 の空白に関する“癖”について
\r
107 * http://kojs.sukobuto.com/docs/visible-binding
\r
108 * IE6 には、「空の span エレメントに続く空白は無視される」という謎な癖があります。
\r
111 X_TEMP._onPreInit =
\r
114 var r = X_Node_body,
\r
116 copy, i, l, node, html,
\r
119 if( !X_TEMP.X_Dom_useBuilder ) return;
\r
121 X_HTMLParser_skipFixNesting = true;
\r
124 // textarea の内容を控えて、消す。xnode tree 構築後に復帰。でないと、html パースでこける
\r
125 //X_UA[ 'MacIE' ] && alert( body.innerHTML );
\r
127 function cleanUpTree( elm, skip ){
\r
128 var nodes = X_Array_copy( elm.childNodes ),
\r
131 node, tag, textNode, content;
\r
132 for( ; i < l; ++i ){
\r
134 switch( node.nodeType ){
\r
136 tag = node.tagName.toUpperCase();
\r
137 if( X_Dom_DTD_MOVE_TO_HEAD[ tag ] ){
\r
138 X_elmHead.appendChild( node );
\r
141 if( X_TEMP._isCleanupTarget( node ) ){
\r
142 elm.removeChild( node );
\r
145 // pre タグ以下はスペースの置換は行わない
\r
146 node.childNodes && node.childNodes.length && cleanUpTree( node, skip || X_Dom_DTD_SKIP_CLEANUP_TAGS[ tag ] );
\r
151 content = skip ? node.data : X_String_cleanupWhiteSpace( node.data );
\r
152 //console.log( 'Delete space ' + node.data.length + ' => ' + content.length );
\r
153 if( !textNode && content !== ' ' && content.length ){
\r
154 node.data = content;
\r
159 textNode.data += content; // 直前が TextNode の場合 一本化して削除
\r
161 // ブロック要素直下のスペースだけは削除??
\r
163 //console.log( 'Remove type: ' + node.nodeType + ' value: ' + node.nodeValue );
\r
164 if( !X_UA[ 'Opera7' ] /*&& !X_UA[ 'MacIE' ] */ ){
\r
165 elm.removeChild( node );
\r
167 X_TEMP._fixed_remove( node );
\r
174 cleanUpTree( X_UA[ 'MacIE' ] ? ( copy = body.cloneNode( true ) ) : body );
\r
176 if( X_UA[ 'MacIE' ] ){
\r
177 document.write( html = copy.innerHTML );
\r
180 if( X_UA[ 'IE' ] <= 8 ){
\r
181 html = body.innerHTML.split( X_String_CRLF ).join( '' ); // 不要な改行が入る
\r
183 html = body.innerHTML;
\r
186 // Nokia s60 Safari
\r
187 if( html === 'fastinnerhtml!' ){
\r
189 for( i = 0, l = body.childNodes.length; i < l; ++i ){
\r
190 node = body.childNodes[ i ];
\r
191 html += ( node.outerHTML || node.data );
\r
196 body.appendChild( X_TEMP.elmProgress = elmProgress = document.createElement( 'div' ) );
\r
197 elmProgress.style.cssText = 'position:absolute;top:0;left:0;z-index:9999;width:0;height:0.5em;background:#00f;overflow:hidden;';
\r
198 elmProgress.setAttribute( 'style', 'position:absolute;top:0;left:0;z-index:9999;width:0;height:0.5em;background:#00f;overflow:hidden;' );
\r
200 X_HTMLParser_asyncParse( html, true )
\r
201 [ 'listen' ]( X_EVENT_PROGRESS, X_TEMP._handleEvent )
\r
202 [ 'listenOnce' ]( X_EVENT_SUCCESS, X_TEMP._handleEvent );
\r
207 var r = X_Node_body,
\r
208 body = r[ '_rawObject' ],
\r
209 elmProgress = '_xdom_builder_progress',
\r
212 if( !X_TEMP.X_Dom_useBuilder ) return;
\r
215 * http://support.microsoft.com/kb/812417/ja
\r
216 * PRB: outerHTML の HTML 要素のプロパティは、既定の属性は表示されません。
\r
218 * body.innerHTML でなく、 body.outerHTML にはできなかった、、、
\r
220 html = body.innerHTML;
\r
221 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
222 X_TEMP.elmProgress = document.all[ elmProgress ];
\r
224 X_HTMLParser_asyncParse( html, true )
\r
225 [ 'listen' ]( X_EVENT_PROGRESS, X_TEMP._handleEvent )
\r
226 [ 'listenOnce' ]( X_EVENT_SUCCESS, X_TEMP._handleEvent );
\r
229 X_ViewPort[ 'listenOnce' ]( X_EVENT_PRE_INIT, X_TEMP._onPreInit );
\r
231 X_TEMP._handleEvent = function( e ){
\r
232 var elmProgress = X_TEMP.elmProgress, xnodes;
\r
235 case X_EVENT_PROGRESS :
\r
236 elmProgress.style.width = ( e.percent * 100 | 0 ) + '%';
\r
239 case X_EVENT_SUCCESS :
\r
240 xnodes = X_Node_body[ '_xnodes' ] = [];
\r
242 xnodes.push.apply( xnodes, e.xnodes );
\r
243 elmProgress.style.width = '100%';
\r
245 X_TEMP.asyncCreateTree( X_Node_body, X_elmBody.childNodes || X_elmBody.children, elmProgress );
\r
247 delete X_TEMP._onPreInit;
\r
248 delete X_TEMP.elmProgress;
\r
253 X_TEMP.asyncCreateTree = function( parent, elems, elmProgress, async ){
\r
254 var xnodes = async ? 0 : X_Array_copy( parent[ '_xnodes' ] ),
\r
255 l = async ? 0 : xnodes.length,
\r
256 stack = async ? async.stack : [],
\r
257 done = async ? async.done : 0,
\r
258 startTime = X_Timer_now(),
\r
259 current = async ? async.current : {
\r
264 elems : X_Array_copy( elems ),
\r
270 //alert( 'X_TEMP.asyncCreateTree' );
\r
271 while( current || ( current = stack.pop() ) ){
\r
275 parent = current.me;
\r
276 xnodes = current.xnodes;
\r
277 while( xnode = xnodes[ i ] ){
\r
279 dive = X_TEMP.bindElementToXnode( parent, xnode, current );
\r
285 stack[ stack.length ] = current;
\r
291 xnodes = dive.xnodes;
\r
295 if( startTime + X_Timer_INTERVAL_TIME <= X_Timer_now() ){
\r
298 async.current = i < l && current;
\r
301 //alert( 'koko?' );
\r
302 X_Timer_once( 0, X_TEMP.asyncCreateTree, [ null, null, elmProgress, async || { stack : stack, current : i < l && current, done : done } ] );
\r
304 elmProgress.style.width = ( ( 1 - done / X_Node_CHASHE.length ) * 100 | 0 ) + '%';
\r
312 console.log( 'xtree 作成完了' );
\r
313 X_ViewPort[ 'asyncDispatch' ]( X_EVENT_XTREE_READY );
\r
315 if( X_UA[ 'IE' ] < 6 ){
\r
316 // IE5.01 でビルド時間が短い時に removeChild を通るとエラー!
\r
317 elmProgress.outerHTML = '';
\r
319 elmProgress.parentNode.removeChild( elmProgress );
\r
322 delete X_TEMP.asyncCreateTree;
\r
323 delete X_TEMP.bindElementToXnode;
\r
324 delete X_TEMP.X_Dom_useBuilder;
\r
325 delete X_TEMP._isCleanupTarget;
\r
327 X_HTMLParser_skipFixNesting = false;
\r
330 X_TEMP.bindElementToXnode =
\r
332 (function( parent, xnode, current ){
\r
333 var elems = current.elems,
\r
336 xtext = current.xtext,
\r
337 skipCleanup = current.skipCleanup,
\r
338 inPreTag = current.inPreTag,
\r
341 xnode.parent = parent;
\r
343 for( ; current.j < m; ++current.j ){
\r
344 elm = elems[ current.j ];
\r
345 tag = elm.tagName && elm.tagName.toUpperCase();
\r
346 if( ( elm.nodeType !== 1 && elm.nodeType !== 3 ) || tag === '!' || ( tag && tag.charAt( 0 ) === '/' ) ){
\r
347 if( !X_UA[ 'Opera7' ] && !X_UA[ 'MacIE' ] ){
\r
348 elm.parentNode.removeChild( elm );
\r
350 X_TEMP._fixed_remove( elm );
\r
355 if( xnode[ '_tag' ] ){
\r
356 if( elm.nodeType === 3 ){
\r
357 if( !( text = elm.data ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
358 //alert( text.charCodeAt( 0 ) );
\r
359 if( !X_UA[ 'Opera7' ] && !X_UA[ 'MacIE' ] ){
\r
360 elm.parentNode.removeChild( elm );
\r
362 X_TEMP._fixed_remove( elm );
\r
366 alert( '1:[' +parent[ '_tag' ] + '>' +xnode[ '_tag' ] + '] !== ' + elm.nodeType + '\n' + ( elm.data ) );
\r
368 if( X_Dom_DTD_MOVE_TO_HEAD[ tag ] ){
\r
372 if( xnode[ '_tag' ] !== tag ){
\r
373 alert( '2:[' +parent[ '_tag' ] + '>' +xnode[ '_tag' ] + ' len:' + (xnode[ '_xnodes' ] ? xnode[ '_xnodes' ].length : '' ) + '] !== ' + tag + ' ' + (elm.childNodes ? elm.childNodes.length : '' ) + '\n' + elm.outerHTML );
\r
375 xnode[ '_rawObject' ] = elm;
\r
376 //if( ( doc = elm.ownerDocument || elm.document ) && ( doc.createElement( 'p' ).tagName === doc.createElement( 'P' ).tagName ) ){
\r
377 if( tag.charAt( 0 ) === '/' ) tag = tag.slice( 1 );
\r
378 xnode[ '_tag' ] = tag;
\r
380 xnode[ '_flags' ] |= X_NodeFlags_IN_TREE;
\r
381 xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
\r
382 elm[ 'UID' ] = xnode[ '_uid' ];
\r
383 current.xtext = null;
\r
385 if( tag === 'TEXTAREA' ){
\r
386 xnode[ 'attr' ]( 'value', xnode[ 'html' ]() )[ 'empty' ]();
\r
389 if( elm.childNodes && elm.childNodes.length ){
\r
390 //alert( '[' +parent[ '_tag' ] + '>' + xnode[ '_tag' ] + ' ' + (xnode[ '_xnodes' ] ? xnode[ '_xnodes' ].length : '' ) + '] === ' + tag + ' ' + (elm.childNodes ? elm.childNodes.length : '' ) + ' Hit\n' + elm.outerHTML );
\r
391 //current.xtext = null;
\r
396 xnodes : X_Array_copy( xnode[ '_xnodes' ] ),
\r
400 l : xnode[ '_xnodes' ].length,
\r
401 elems : X_Array_copy( elm.childNodes ),
\r
403 skipCleanup : skipCleanup || X_Dom_DTD_SKIP_CLEANUP_TAGS[ tag ]
\r
407 //current.xtext = null;
\r
413 if( elm.nodeType !== 3 ){
\r
414 if( !( text = xnode[ '_text' ] ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
415 console.log( '[' +parent[ '_tag' ] + '> UID:' + xnode[ '_uid' ] + ' len:' + xnode[ '_text' ].length + ' code : ' + xnode[ '_text' ].charCodeAt( 0 ) + ',' + xnode[ '_text' ].charCodeAt( 1 ) + '] destroyed.' );
\r
419 alert( parent[ '_tag' ] + ' > ' + '"' + xnode[ '_text' ] + '" !== ' + tag + '\n' +
\r
420 'prev : ' + ( xnode[ 'prev' ]() && xnode[ 'prev' ]()[ 'html' ]() ) + '\n' +
\r
421 'next : ' + ( xnode[ 'next' ]() && xnode[ 'next' ]()[ 'html' ]() ) + '\n' +
\r
422 'html : ' + elm.outerHTML );
\r
427 xnode[ '_rawObject' ] = elm;
\r
428 xnode[ '_flags' ] |= X_NodeFlags_IN_TREE;
\r
429 xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
\r
430 xnode[ '_text' ] = elm.data; // 正確
\r
432 if( !skipCleanup ){
\r
433 if( !( text = xnode[ '_text' ] ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
434 console.log( '[' +parent[ '_tag' ] + '>' + xnode[ '_uid' ] + '] destroy ... ' );
\r
438 xtext[ 'text' ]( xtext[ '_text' ] + text );
\r
439 console.log( '[' +parent[ '_tag' ] + '>' + xnode[ '_uid' ] + '] xtext,destroy ... ' );
\r
442 //alert( parent[ '_tag' ] + '>' + '"' + text + '"\n' + elm.data );
\r
443 xnode[ 'text' ]( text );
\r
447 xtext[ 'text' ]( xtext[ '_text' ] + xnode[ '_text' ] );
\r
448 console.log( '[' +parent[ '_tag' ] + '>' + xnode[ '_uid' ] + '] xtext,destroy ... ' );
\r
451 current.xtext = xtext || xnode;
\r
455 (function ( parent, xnode, current ){
\r
456 var elems = current.elems,
\r
459 xtext = current.xtext,
\r
460 skipCleanup = current.skipCleanup,
\r
463 xnode.parent = parent;
\r
465 if( !xnode[ '_tag' ] ){
\r
466 xnode[ '_flags' ] |= X_NodeFlags_IN_TREE;
\r
467 xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
\r
468 //alert( X_String_cleanupWhiteSpace( xnode[ '_text' ] ) );
\r
469 if( !skipCleanup ){
\r
470 if( !( text = xnode[ '_text' ] ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
475 //alert( 'xtext ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
476 xtext[ 'text' ]( xtext[ '_text' ] + text );
\r
479 //alert( 'xnode ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
480 xnode[ 'text' ]( text );
\r
484 //alert( 'skip ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
485 xtext[ 'text' ]( xtext[ '_text' ] + xnode[ '_text' ] );
\r
489 current.xtext = xtext || xnode;
\r
490 parent[ '_flags' ] |= X_NodeFlags_IE4_HAS_TEXTNODE;
\r
494 for( ; j < m; ++j, ++current.j ){
\r
498 * 未知のタグについては、閉じタグも含めてタグ名扱いになる
\r
500 if( tag === '!' || tag.charAt( 0 ) === '/' ){
\r
501 //alert( '## ' + tag );
\r
504 if( xnode[ '_tag' ] !== tag ){
\r
505 alert( xnode[ '_tag' ] + ' ' + ' !== ' + tag + '\nxnode.html():' + xnode.attr('cite') + '\nelm.outerHTML:' + elm.outerHTML );
\r
509 xnode[ '_rawObject' ] = elm;
\r
510 xnode[ '_flags' ] |= X_NodeFlags_IN_TREE;
\r
511 xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
\r
512 //xnode[ '_tag' ] = X_Dom_DTD_TAG_FIX[ tag ] || tag;
\r
513 if( X_TEMP._isCleanupTarget( elm ) ){ //!xnode[ 'hasClass' ]( 'skip-cleanup' ) && ( X_Dom_DTD_CLEANUP_TAGS[ tag ] || xnode[ 'hasClass' ]( 'cleanup-target' ) ) ){
\r
518 !xnode[ '_id' ] && elm.setAttribute( 'id', 'ie4uid' + xnode[ '_uid' ] );
\r
519 elm.setAttribute( 'UID', xnode[ '_uid' ] );
\r
521 tag === 'INPUT' && (
\r
522 !xnode[ '_attrs' ] ?
\r
523 ( xnode[ '_attrs' ] = { type : 'text' } ) :
\r
524 xnode[ '_attrs' ].type || ( xnode[ '_attrs' ].type = 'text' )
\r
526 parent[ '_flags' ] |= X_NodeFlags_IE4_HAS_ELEMENT;
\r
527 current.xtext = null;
\r
529 if( tag === 'TEXTAREA' ){
\r
530 xnode[ 'attr' ]( 'value', xnode[ 'html' ]() )[ 'empty' ]();
\r
532 if( xnode[ '_xnodes' ] && xnode[ '_xnodes' ].length ){
\r
535 xnodes : X_Array_copy( xnode[ '_xnodes' ] ),
\r
539 l : xnode[ '_xnodes' ].length,
\r
540 elems : X_Array_copy( elm.children ),
\r
542 skipCleanup : skipCleanup || X_Dom_DTD_SKIP_CLEANUP_TAGS[ tag ]
\r
549 if( !xnode[ '_rawObject' ] ){
\r
550 alert( xnode[ '_tag' ] + ' ' + xnode[ '_id' ] + ' !== none...' );
\r
554 console.log( 'X.Dom.Builder' );
\r
555 console.log( 'bootTime : ' + ( X_Timer_now() - X.bootTime ) );