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 document.body.appendChild( node );
\r
45 parent.replaceChild( document.createComment( '' ), node ); */
\r
46 document.body.appendChild( node );
\r
48 if( parent.parentNode !== document.body ){
\r
49 var clone = parent.cloneNode( true );
\r
50 for( var i = 0, l = parent.childNodes.length; i < l; ++i ){
\r
51 if( parent.childNodes[ i ] !== node ){
\r
52 clone.removeChild( clone.childNodes[ i ] );
\r
55 //parent.parentNode.insertBefore( clone, parent );
\r
56 //parent.parentNode.removeChild( parent );
\r
57 parent.parentNode.insertBefore( clone, parent );
\r
58 parent.style.display = 'none';
\r
60 xnode.parent.parent[ '_rawObject' ] = clone;
\r
67 //if( !node.ownerDocument ) alert( 'no owner' );
\r
73 X_TEMP._removalTextNodes = [];
\r
75 X_TEMP._timerRemove = function(){
\r
76 var nodes = X_TEMP._removalTextNodes,
\r
78 while( i < 5 && nodes.length ){
\r
79 node = nodes.shift();
\r
80 if( node.parentNode ){
\r
81 //node.parentNode.removeChild( node );
\r
86 //nodes.length && X_Timer_once( 1000, X_TEMP._timerRemove );
\r
90 if( X_UA[ 'Opera7' ] ){
\r
92 X_TEMP._fixed_remove = function( node ){
\r
93 if( node.nodeType === 1 || node.nodeType === 3 ){
\r
94 node.parentNode && node.parentNode.removeChild( node );
\r
101 /* --------------------------------------
\r
102 * 通常のwebページに対して使用する場合、dom ready で dom tree を写し取るために使う.
\r
103 * 完全にワンページアプリで<body/>が空な場合、このコードはビルドに含める必要はない
\r
105 * TODO (注4) IE6 の空白に関する“癖”について
\r
106 * http://kojs.sukobuto.com/docs/visible-binding
\r
107 * IE6 には、「空の span エレメントに続く空白は無視される」という謎な癖があります。
\r
110 X_TEMP._onPreInit =
\r
113 var r = X_Node_body,
\r
114 body = r[ '_rawObject' ],
\r
115 copy, i, l, node, html,
\r
118 if( !X_TEMP.X_Dom_useBuilder ) return;
\r
120 X_HTMLParser_skipFixNesting = true;
\r
123 // textarea の内容を控えて、消す。xnode tree 構築後に復帰。でないと、html パースでこける
\r
124 //X_UA[ 'MacIE' ] && alert( body.innerHTML );
\r
126 function cleanUpTree( elm, skip, head ){
\r
127 var nodes = X_Object_cloneArray( elm.childNodes ),
\r
130 node, tag, textNode, content;
\r
131 for( ; i < l; ++i ){
\r
133 switch( node.nodeType ){
\r
135 tag = node.tagName.toUpperCase();
\r
136 if( X_Dom_DTD_MOVE_TO_HEAD[ tag ] ){
\r
137 head = head || document.getElementsByTagName( 'head' )[ 0 ];
\r
138 head.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 ], head );
\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_TEMP._body = body;
\r
202 X_HTMLParser_asyncParse( html, true )
\r
203 [ 'listen' ]( X_EVENT_PROGRESS, X_TEMP._handleEvent )
\r
204 [ 'listenOnce' ]( X_EVENT_SUCCESS, X_TEMP._handleEvent );
\r
209 var r = X_Node_body,
\r
210 body = r[ '_rawObject' ],
\r
211 elmProgress = '_xdom_builder_progress',
\r
214 if( !X_TEMP.X_Dom_useBuilder ) return;
\r
217 * http://support.microsoft.com/kb/812417/ja
\r
218 * PRB: outerHTML の HTML 要素のプロパティは、既定の属性は表示されません。
\r
220 * body.innerHTML でなく、 body.outerHTML にはできなかった、、、
\r
222 html = body.innerHTML;
\r
223 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
224 X_TEMP.elmProgress = document.all[ elmProgress ];
\r
226 X_TEMP._body = body;
\r
228 X_HTMLParser_asyncParse( html, true )
\r
229 [ 'listen' ]( X_EVENT_PROGRESS, X_TEMP._handleEvent )
\r
230 [ 'listenOnce' ]( X_EVENT_SUCCESS, X_TEMP._handleEvent );
\r
233 X_ViewPort[ 'listenOnce' ]( X_EVENT_PRE_INIT, X_TEMP._onPreInit );
\r
235 X_TEMP._handleEvent = function( e ){
\r
236 var elmProgress = X_TEMP.elmProgress, xnodes;
\r
239 case X_EVENT_PROGRESS :
\r
240 elmProgress.style.width = ( e.percent * 100 | 0 ) + '%';
\r
243 case X_EVENT_SUCCESS :
\r
244 xnodes = X_Node_body[ '_xnodes' ] = [];
\r
246 xnodes.push.apply( xnodes, e.xnodes );
\r
247 elmProgress.style.width = '100%';
\r
249 X_TEMP.asyncCreateTree( X_Node_body, X_TEMP._body.childNodes || X_TEMP._body.children, elmProgress );
\r
251 delete X_TEMP._onPreInit;
\r
252 delete X_TEMP._body;
\r
253 delete X_TEMP.elmProgress;
\r
258 X_TEMP.asyncCreateTree = function( parent, elems, elmProgress, async ){
\r
259 var xnodes = async ? 0 : X_Object_cloneArray( parent[ '_xnodes' ] ),
\r
260 l = async ? 0 : xnodes.length,
\r
261 stack = async ? async.stack : [],
\r
262 done = async ? async.done : 0,
\r
263 startTime = X_Timer_now(),
\r
264 current = async ? async.current : {
\r
269 elems : X_Object_cloneArray( elems ),
\r
275 //alert( 'X_TEMP.asyncCreateTree' );
\r
276 while( current || ( current = stack.pop() ) ){
\r
280 parent = current.me;
\r
281 xnodes = current.xnodes;
\r
282 while( xnode = xnodes[ i ] ){
\r
284 dive = X_TEMP.bindElementToXnode( parent, xnode, current );
\r
290 stack[ stack.length ] = current;
\r
296 xnodes = dive.xnodes;
\r
300 if( startTime + 16 <= X_Timer_now() ){
\r
303 async.current = i < l && current;
\r
306 //alert( 'koko?' );
\r
307 X_Timer_once( 0, X_TEMP.asyncCreateTree, [ null, null, elmProgress, async || { stack : stack, current : i < l && current, done : done } ] );
\r
309 elmProgress.style.width = ( ( 1 - done / X_Node_CHASHE.length ) * 100 | 0 ) + '%';
\r
317 console.log( 'xtree 作成完了' );
\r
318 X_ViewPort[ 'asyncDispatch' ]( X_EVENT_XTREE_READY );
\r
319 elmProgress.parentNode ? elmProgress.parentNode.removeChild( elmProgress ) : ( elmProgress.outerHTML = '' );
\r
321 delete X_TEMP.asyncCreateTree;
\r
322 delete X_TEMP.bindElementToXnode;
\r
323 delete X_TEMP.X_Dom_useBuilder;
\r
324 delete X_TEMP._isCleanupTarget;
\r
326 X_HTMLParser_skipFixNesting = false;
\r
329 X_TEMP.bindElementToXnode =
\r
331 (function( parent, xnode, current ){
\r
332 var elems = current.elems,
\r
335 xtext = current.xtext,
\r
336 skipCleanup = current.skipCleanup,
\r
337 inPreTag = current.inPreTag,
\r
340 xnode.parent = parent;
\r
342 for( ; current.j < m; ++current.j ){
\r
343 elm = elems[ current.j ];
\r
344 tag = elm.tagName && elm.tagName.toUpperCase();
\r
345 if( ( elm.nodeType !== 1 && elm.nodeType !== 3 ) || tag === '!' || ( tag && tag.charAt( 0 ) === '/' ) ){
\r
346 if( !X_UA[ 'Opera7' ] && !X_UA[ 'MacIE' ] ){
\r
347 elm.parentNode.removeChild( elm );
\r
349 X_TEMP._fixed_remove( elm );
\r
354 if( xnode[ '_tag' ] ){
\r
355 if( elm.nodeType === 3 ){
\r
356 if( !( text = elm.data ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
357 //alert( text.charCodeAt( 0 ) );
\r
358 if( !X_UA[ 'Opera7' ] && !X_UA[ 'MacIE' ] ){
\r
359 elm.parentNode.removeChild( elm );
\r
361 X_TEMP._fixed_remove( elm );
\r
365 alert( '1:[' +parent[ '_tag' ] + '>' +xnode[ '_tag' ] + '] !== ' + elm.nodeType + '\n' + ( elm.data ) );
\r
367 if( X_Dom_DTD_MOVE_TO_HEAD[ tag ] ){
\r
371 if( xnode[ '_tag' ] !== tag ){
\r
372 alert( '2:[' +parent[ '_tag' ] + '>' +xnode[ '_tag' ] + ' len:' + (xnode[ '_xnodes' ] ? xnode[ '_xnodes' ].length : '' ) + '] !== ' + tag + ' ' + (elm.childNodes ? elm.childNodes.length : '' ) + '\n' + elm.outerHTML );
\r
374 xnode[ '_rawObject' ] = elm;
\r
375 //if( ( doc = elm.ownerDocument || elm.document ) && ( doc.createElement( 'p' ).tagName === doc.createElement( 'P' ).tagName ) ){
\r
376 if( tag.charAt( 0 ) === '/' ) tag = tag.slice( 1 );
\r
377 xnode[ '_tag' ] = tag;
\r
379 xnode[ '_flags' ] |= X_NodeFlags_IN_TREE;
\r
380 xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
\r
381 elm[ 'UID' ] = xnode[ '_uid' ];
\r
382 current.xtext = null;
\r
384 if( tag === 'TEXTAREA' ){
\r
385 xnode[ 'attr' ]( 'value', xnode[ 'html' ]() )[ 'empty' ]();
\r
388 if( elm.childNodes && elm.childNodes.length ){
\r
389 //alert( '[' +parent[ '_tag' ] + '>' + xnode[ '_tag' ] + ' ' + (xnode[ '_xnodes' ] ? xnode[ '_xnodes' ].length : '' ) + '] === ' + tag + ' ' + (elm.childNodes ? elm.childNodes.length : '' ) + ' Hit\n' + elm.outerHTML );
\r
390 //current.xtext = null;
\r
395 xnodes : X_Object_cloneArray( xnode[ '_xnodes' ] ),
\r
399 l : xnode[ '_xnodes' ].length,
\r
400 elems : X_Object_cloneArray( elm.childNodes ),
\r
402 skipCleanup : skipCleanup || X_Dom_DTD_SKIP_CLEANUP_TAGS[ tag ]
\r
406 //current.xtext = null;
\r
412 if( elm.nodeType !== 3 ){
\r
413 if( !( text = xnode[ '_text' ] ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
414 console.log( '[' +parent[ '_tag' ] + '> UID:' + xnode[ '_uid' ] + ' len:' + xnode[ '_text' ].length + ' code : ' + xnode[ '_text' ].charCodeAt( 0 ) + ',' + xnode[ '_text' ].charCodeAt( 1 ) + '] destroyed.' );
\r
418 alert( parent[ '_tag' ] + ' > ' + '"' + xnode[ '_text' ] + '" !== ' + tag + '\n' +
\r
419 'prev : ' + ( xnode[ 'prev' ]() && xnode[ 'prev' ]()[ 'html' ]() ) + '\n' +
\r
420 'next : ' + ( xnode[ 'next' ]() && xnode[ 'next' ]()[ 'html' ]() ) + '\n' +
\r
421 'html : ' + elm.outerHTML );
\r
426 xnode[ '_rawObject' ] = elm;
\r
427 xnode[ '_flags' ] |= X_NodeFlags_IN_TREE;
\r
428 xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
\r
429 xnode[ '_text' ] = elm.data; // 正確
\r
431 if( !skipCleanup ){
\r
432 if( !( text = xnode[ '_text' ] ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
433 console.log( '[' +parent[ '_tag' ] + '>' + xnode[ '_uid' ] + '] destroy ... ' );
\r
437 xtext[ 'text' ]( xtext[ '_text' ] + text );
\r
438 console.log( '[' +parent[ '_tag' ] + '>' + xnode[ '_uid' ] + '] xtext,destroy ... ' );
\r
441 //alert( parent[ '_tag' ] + '>' + '"' + text + '"\n' + elm.data );
\r
442 xnode[ 'text' ]( text );
\r
446 xtext[ 'text' ]( xtext[ '_text' ] + xnode[ '_text' ] );
\r
447 console.log( '[' +parent[ '_tag' ] + '>' + xnode[ '_uid' ] + '] xtext,destroy ... ' );
\r
450 current.xtext = xtext || xnode;
\r
454 (function ( parent, xnode, current ){
\r
455 var elems = current.elems,
\r
458 xtext = current.xtext,
\r
459 skipCleanup = current.skipCleanup,
\r
462 xnode.parent = parent;
\r
464 if( !xnode[ '_tag' ] ){
\r
465 xnode[ '_flags' ] |= X_NodeFlags_IN_TREE;
\r
466 xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
\r
467 //alert( X_String_cleanupWhiteSpace( xnode[ '_text' ] ) );
\r
468 if( !skipCleanup ){
\r
469 if( !( text = xnode[ '_text' ] ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
474 //alert( 'xtext ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
475 xtext[ 'text' ]( xtext[ '_text' ] + text );
\r
478 //alert( 'xnode ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
479 xnode[ 'text' ]( text );
\r
483 //alert( 'skip ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
484 xtext[ 'text' ]( xtext[ '_text' ] + xnode[ '_text' ] );
\r
488 current.xtext = xtext || xnode;
\r
489 parent[ '_flags' ] |= X_NodeFlags_IE4_HAS_TEXTNODE;
\r
493 for( ; j < m; ++j, ++current.j ){
\r
497 * 未知のタグについては、閉じタグも含めてタグ名扱いになる
\r
499 if( tag === '!' || tag.charAt( 0 ) === '/' ){
\r
500 //alert( '## ' + tag );
\r
503 if( xnode[ '_tag' ] !== tag ){
\r
504 alert( xnode[ '_tag' ] + ' ' + ' !== ' + tag + '\nxnode.html():' + xnode.attr('cite') + '\nelm.outerHTML:' + elm.outerHTML );
\r
508 xnode[ '_rawObject' ] = elm;
\r
509 xnode[ '_flags' ] |= X_NodeFlags_IN_TREE;
\r
510 xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
\r
511 //xnode[ '_tag' ] = X_Dom_DTD_TAG_FIX[ tag ] || tag;
\r
512 if( X_TEMP._isCleanupTarget( elm ) ){ //!xnode[ 'hasClass' ]( 'skip-cleanup' ) && ( X_Dom_DTD_CLEANUP_TAGS[ tag ] || xnode[ 'hasClass' ]( 'cleanup-target' ) ) ){
\r
517 !xnode[ '_id' ] && elm.setAttribute( 'id', 'ie4uid' + xnode[ '_uid' ] );
\r
518 elm.setAttribute( 'UID', xnode[ '_uid' ] );
\r
520 tag === 'INPUT' && (
\r
521 !xnode[ '_attrs' ] ?
\r
522 ( xnode[ '_attrs' ] = { type : 'text' } ) :
\r
523 xnode[ '_attrs' ].type || ( xnode[ '_attrs' ].type = 'text' )
\r
525 parent[ '_flags' ] |= X_NodeFlags_IE4_HAS_ELEMENT;
\r
526 current.xtext = null;
\r
528 if( tag === 'TEXTAREA' ){
\r
529 xnode[ 'attr' ]( 'value', xnode[ 'html' ]() )[ 'empty' ]();
\r
531 if( xnode[ '_xnodes' ] && xnode[ '_xnodes' ].length ){
\r
534 xnodes : X_Object_cloneArray( xnode[ '_xnodes' ] ),
\r
538 l : xnode[ '_xnodes' ].length,
\r
539 elems : X_Object_cloneArray( elm.children ),
\r
541 skipCleanup : skipCleanup || X_Dom_DTD_SKIP_CLEANUP_TAGS[ tag ]
\r
548 if( !xnode[ '_rawObject' ] ){
\r
549 alert( xnode[ '_tag' ] + ' ' + xnode[ '_id' ] + ' !== none...' );
\r
553 console.log( 'X.Dom.Builder' );
\r
554 console.log( 'bootTime : ' + ( X_Timer_now() - X.bootTime ) );