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_TEMP.SYSTEM_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, function( e ){
\r
203 var xnodes = X_Node_body._xnodes = [], t;
\r
204 xnodes.push.apply( xnodes, e.xnodes );
\r
205 elmProgress.style.width = '100%';
\r
207 X_TEMP.asyncCreateTree( X_Node_body, body.childNodes, elmProgress );
\r
213 var r = X_Node_body,
\r
214 body = r._rawObject,
\r
215 elmProgress = '_xdom_builder_progress',
\r
219 if( !X_TEMP.X_Dom_useBuilder ) return;
\r
222 * http://support.microsoft.com/kb/812417/ja
\r
223 * PRB: outerHTML の HTML 要素のプロパティは、既定の属性は表示されません。
\r
225 * body.innerHTML でなく、 body.outerHTML にはできなかった、、、
\r
227 html = body.innerHTML;
\r
228 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
229 elmProgress = document.all[ elmProgress ];
\r
231 X_HTMLParser_asyncParse( html, true )
\r
232 .listen( X_Event.PROGRESS,
\r
234 elmProgress.style.width = ( e.percent * 100 | 0 ) + '%';
\r
237 .listenOnce( X_Event.SUCCESS,
\r
239 var xnodes = X_Node_body._xnodes = [], t;
\r
240 xnodes.push.apply( xnodes, e.xnodes );
\r
241 elmProgress.style.width = '100%';
\r
243 X_TEMP.asyncCreateTree( X_Node_body, body.childNodes || body.children, elmProgress );
\r
251 X_TEMP.asyncCreateTree = function ( parent, elems, elmProgress, async ){
\r
252 var xnodes = async ? 0 : X_Object_cloneArray( parent._xnodes ),
\r
253 l = async ? 0 : xnodes.length,
\r
254 stack = async ? async.stack : [],
\r
255 done = async ? async.done : 0,
\r
256 startTime = X_Timer_now(),
\r
257 current = async ? async.current : {
\r
262 elems : X_Object_cloneArray( elems ),
\r
268 //alert( 'X_TEMP.asyncCreateTree' );
\r
269 while( current || ( current = stack.pop() ) ){
\r
273 parent = current.me;
\r
274 xnodes = current.xnodes;
\r
275 while( xnode = xnodes[ i ] ){
\r
277 dive = X_TEMP.bindElementToXnode( parent, xnode, current );
\r
283 stack[ stack.length ] = current;
\r
289 xnodes = dive.xnodes;
\r
293 if( startTime + 16 <= X_Timer_now() ){
\r
296 async.current = i < l && current;
\r
299 //alert( 'koko?' );
\r
300 X.Timer.once( 0, X_TEMP.asyncCreateTree, [ null, null, elmProgress, async || { stack : stack, current : i < l && current, done : done } ] );
\r
302 elmProgress.style.width = ( ( 1 - done / X_Node_CHASHE.length ) * 100 | 0 ) + '%';
\r
310 X_ViewPort.asyncDispatch( X_TEMP.SYSTEM_EVENT_XTREE );
\r
311 elmProgress.parentNode ? elmProgress.parentNode.removeChild( elmProgress ) : ( elmProgress.outerHTML = '' );
\r
312 delete X_TEMP.asyncCreateTree;
\r
313 delete X_TEMP.bindElementToXnode;
\r
314 delete X_TEMP.X_Dom_useBuilder;
\r
315 delete X_TEMP._isCleanupTarget;
\r
317 X_HTMLParser_skipFixNesting = false;
\r
320 X_TEMP.bindElementToXnode =
\r
322 (function( parent, xnode, current ){
\r
323 var elems = current.elems,
\r
326 xtext = current.xtext,
\r
327 skipCleanup = current.skipCleanup,
\r
328 inPreTag = current.inPreTag,
\r
331 xnode.parent = parent;
\r
333 for( ; current.j < m; ++current.j ){
\r
334 elm = elems[ current.j ];
\r
335 tag = elm.tagName && elm.tagName.toUpperCase();
\r
336 if( ( elm.nodeType !== 1 && elm.nodeType !== 3 ) || tag === '!' || ( tag && tag.charAt( 0 ) === '/' ) ){
\r
337 if( !X_UA[ 'Opera7' ] && !X_UA[ 'MacIE' ] ){
\r
338 elm.parentNode.removeChild( elm );
\r
340 X_TEMP._fixed_remove( elm );
\r
346 if( elm.nodeType === 3 ){
\r
347 if( !( text = elm.data ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
348 //alert( text.charCodeAt( 0 ) );
\r
349 if( !X_UA[ 'Opera7' ] && !X_UA[ 'MacIE' ] ){
\r
350 elm.parentNode.removeChild( elm );
\r
352 X_TEMP._fixed_remove( elm );
\r
356 alert( '1:[' +parent._tag + '>' +xnode._tag + '] !== ' + elm.nodeType + '\n' + ( elm.data ) );
\r
358 if( X_Dom_DTD_MOVE_TO_HEAD[ tag ] ){
\r
362 if( xnode._tag !== tag ){
\r
363 alert( '2:[' +parent._tag + '>' +xnode._tag + ' len:' + (xnode._xnodes ? xnode._xnodes.length : '' ) + '] !== ' + tag + ' ' + (elm.childNodes ? elm.childNodes.length : '' ) + '\n' + elm.outerHTML );
\r
365 xnode._rawObject = elm;
\r
366 //if( ( doc = elm.ownerDocument || elm.document ) && ( doc.createElement( 'p' ).tagName === doc.createElement( 'P' ).tagName ) ){
\r
367 if( tag.charAt( 0 ) === '/' ) tag = tag.slice( 1 );
\r
370 xnode._flags |= X_Node_State.IN_TREE;
\r
371 xnode._flags &= X_Node_BitMask_RESET_DIRTY;
\r
372 elm.UID = xnode._uid;
\r
373 current.xtext = null;
\r
375 if( tag === 'TEXTAREA' ){
\r
376 xnode.attr( 'value', xnode.html() ).empty();
\r
379 if( elm.childNodes && elm.childNodes.length ){
\r
380 //alert( '[' +parent._tag + '>' + xnode._tag + ' ' + (xnode._xnodes ? xnode._xnodes.length : '' ) + '] === ' + tag + ' ' + (elm.childNodes ? elm.childNodes.length : '' ) + ' Hit\n' + elm.outerHTML );
\r
381 //current.xtext = null;
\r
386 xnodes : X_Object_cloneArray( xnode._xnodes ),
\r
390 l : xnode._xnodes.length,
\r
391 elems : X_Object_cloneArray( elm.childNodes ),
\r
393 skipCleanup : skipCleanup || X_Dom_DTD_SKIP_CLEANUP_TAGS[ tag ]
\r
397 //current.xtext = null;
\r
403 if( elm.nodeType !== 3 ){
\r
404 if( !( text = xnode._text ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
405 console.log( '[' +parent._tag + '> UID:' + xnode._uid + ' len:' + xnode._text.length + ' code : ' + xnode._text.charCodeAt( 0 ) + ',' + xnode._text.charCodeAt( 1 ) + '] destroyed.' );
\r
409 alert( parent._tag + ' > ' + '"' + xnode._text + '" !== ' + tag + '\n' +
\r
410 'prev : ' + ( xnode.prev() && xnode.prev().html() ) + '\n' +
\r
411 'next : ' + ( xnode.next() && xnode.next().html() ) + '\n' +
\r
412 'html : ' + elm.outerHTML );
\r
417 xnode._rawObject = elm;
\r
418 xnode._flags |= X_Node_State.IN_TREE;
\r
419 xnode._flags &= X_Node_BitMask_RESET_DIRTY;
\r
420 xnode._text = elm.data; // 正確
\r
422 if( !skipCleanup ){
\r
423 if( !( text = xnode._text ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
424 console.log( '[' +parent._tag + '>' + xnode._uid + '] destroy ... ' );
\r
428 xtext.text( xtext._text + text );
\r
429 console.log( '[' +parent._tag + '>' + xnode._uid + '] xtext,destroy ... ' );
\r
432 //alert( parent._tag + '>' + '"' + text + '"\n' + elm.data );
\r
433 xnode.text( text );
\r
437 xtext.text( xtext._text + xnode._text );
\r
438 console.log( '[' +parent._tag + '>' + xnode._uid + '] xtext,destroy ... ' );
\r
441 current.xtext = xtext || xnode;
\r
445 (function ( parent, xnode, current ){
\r
446 var elems = current.elems,
\r
449 xtext = current.xtext,
\r
450 skipCleanup = current.skipCleanup,
\r
453 xnode.parent = parent;
\r
456 xnode._flags |= X_Node_State.IN_TREE;
\r
457 xnode._flags &= X_Node_BitMask_RESET_DIRTY;
\r
458 //alert( X_String_cleanupWhiteSpace( xnode._text ) );
\r
459 if( !skipCleanup ){
\r
460 if( !( text = xnode._text ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){
\r
465 //alert( 'xtext ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
466 xtext.text( xtext._text + text );
\r
469 //alert( 'xnode ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
470 xnode.text( text );
\r
474 //alert( 'skip ' + text.charCodeAt( 0 ) + ' : ' + text.length );
\r
475 xtext.text( xtext._text + xnode._text );
\r
479 current.xtext = xtext || xnode;
\r
480 parent._flags |= X_Node_State.IE4_HAS_TEXTNODE;
\r
484 for( ; j < m; ++j, ++current.j ){
\r
488 * 未知のタグについては、閉じタグも含めてタグ名扱いになる
\r
490 if( tag === '!' || tag.charAt( 0 ) === '/' ){
\r
491 //alert( '## ' + tag );
\r
494 if( xnode._tag !== tag ){
\r
495 alert( xnode._tag + ' ' + ' !== ' + tag + '\nxnode.html():' + xnode.attr('cite') + '\nelm.outerHTML:' + elm.outerHTML );
\r
499 xnode._rawObject = elm;
\r
500 xnode._flags |= X_Node_State.IN_TREE;
\r
501 xnode._flags &= X_Node_BitMask_RESET_DIRTY;
\r
502 //xnode._tag = X_Dom_DTD_TAG_FIX[ tag ] || tag;
\r
503 if( X_TEMP._isCleanupTarget( elm ) ){ //!xnode.hasClass( 'skip-cleanup' ) && ( X_Dom_DTD_CLEANUP_TAGS[ tag ] || xnode.hasClass( 'cleanup-target' ) ) ){
\r
508 !xnode._id && elm.setAttribute( 'id', 'ie4uid' + xnode._uid );
\r
509 elm.setAttribute( 'UID', xnode._uid );
\r
511 tag === 'INPUT' && (
\r
513 ( xnode._attrs = { type : 'text' } ) :
\r
514 xnode._attrs.type || ( xnode._attrs.type = 'text' )
\r
516 parent._flags |= X_Node_State.IE4_HAS_ELEMENT;
\r
517 current.xtext = null;
\r
519 if( tag === 'TEXTAREA' ){
\r
520 xnode.attr( 'value', xnode.html() ).empty();
\r
522 if( xnode._xnodes && xnode._xnodes.length ){
\r
525 xnodes : X_Object_cloneArray( xnode._xnodes ),
\r
529 l : xnode._xnodes.length,
\r
530 elems : X_Object_cloneArray( elm.children ),
\r
532 skipCleanup : skipCleanup || X_Dom_DTD_SKIP_CLEANUP_TAGS[ tag ]
\r
539 if( !xnode._rawObject ){
\r
540 alert( xnode._tag + ' ' + xnode._id + ' !== none...' );
\r
544 console.log( 'X.Dom.Builder' );
\r
545 console.log( 'bootTime : ' + ( X_Timer_now() - X.bootTime ) );