\r
+X.Dom.Dirty = {\r
+ CLEAN : 0,\r
+ TREE : 1, // width, height, x, y\r
+ CONTENT : 2, // width, height, x, y textNode の内容\r
+ CLASSNAME : 4, // _getCharSize, width, height, x, y\r
+ CSS : 8, // _getCharSize, width, height, x, y\r
+ ATTR : 16, // _getCharSize, width, height, x, y\r
+ IE4_TEXTNODE_FIX : 32\r
+};\r
+\r
/*\r
* Node( rawElement | rawTextnode | htmlString | textString )\r
*/\r
X.Class.POOL_OBJECT,\r
{\r
_uid : 0,\r
- _rawNode : null, \r
- parent : null, \r
+ _state : 0,\r
+ _destroyed : false,\r
+ _dirty : 0, \r
+ \r
+ _rawNode : null,\r
+ _root : null, \r
+ parent : null,\r
_xnodes : null,\r
\r
_xnodeType : 0,\r
_text : null,\r
_id : null,\r
_className : '',\r
- _classText : ' ',\r
\r
_attrs : null, // X.Dom.Attr\r
+ _newAttrs : null,\r
_attrText : '',\r
- _attrUpdated : false,\r
+ \r
_css : null, // X.Dom.Style\r
_cssText : '',\r
- _styleText : '',\r
\r
Constructor : function( v ){\r
var css, xnodes, xnode, parent, uid = Node._chashe.length;\r
Node._newByText = false;\r
this._text = v;\r
this._xnodeType = 3;\r
+ this._charCode = '';\r
+ for( v = 0; v < this._text.length; ++v ){\r
+ this._charCode += this._text.charCodeAt( v ) + ',';\r
+ };\r
} else {\r
if( 1 < arguments.length ) return new X.Dom.NodeList( arguments );\r
if( X.Type.isArray( v ) && v.length ) return new X.Dom.NodeList( v );\r
if( xnode = Node._getXNode( v ) ) return xnode;\r
// v.parentNode || v.parentElement : dom1 || dom0\r
this.parent = v !== document.body && ( parent = v.parentNode || v.parentElement ) && parent.tagName /* ie7- */ && Node._getXNode( parent );\r
+ this._state = this.parent ? Node.STATE_STAGED : Node.STATE_NO_PARENT;\r
this._rawNode = v;\r
this._xnodeType = 1;\r
this._tag = v.tagName;\r
this._id = v.id;\r
this._className = v.className;\r
- this._classText = ' class="' + this._className + '" ';\r
this.cssText( v.style.cssText );\r
// attr\r
\r
case Node.IS_RAW_TEXT :\r
if( xnode = Node._getXNode( v ) ) return xnode;\r
this.parent = Node._getXNode( v.parentNode );\r
+ this._state = this.parent ? Node.STATE_STAGED : Node.STATE_NO_PARENT;\r
this._rawNode = v;\r
this._xnodeType = 3;\r
this._text = v.data;\r
+ v.UID = uid;\r
break;\r
case Node.IS_HTML_STRING :\r
case Node.IS_STRING :\r
if( xnodes = X.Dom.parse( v, true ) && 1 < xnodes.length ) return new X.Dom.NodeList( xnodes );\r
if( xnodes.length ) return xnodes[ 0 ];\r
return Node.none;\r
+ case Node.IS_IMAGE :\r
+ v.UID = uid;\r
case Node.IS_WINDOW :\r
case Node.IS_DOCUMENT :\r
- case Node.IS_IMAGE :\r
this._rawNode = v;\r
this._xnodeType = 2;\r
+ this._state = Node.STATE_STAGED;\r
break;\r
default :\r
if( Node.none ) return Node.none;\r
}\r
);\r
\r
-var Node = X.Dom.Node;\r
+var Node = X._shortcut = X.Dom.Node;\r
\r
Node.IS_XNODE = 1;\r
Node.IS_RAW_HTML = 2;\r
Node.IS_RAW_TEXT = 3;\r
Node.IS_HTML_STRING = 4;\r
Node.IS_STRING = 5;\r
-Node.IS_DOC_FRAG = 6;\r
+//Node.IS_DOC_FRAG = 6;\r
Node.IS_XNODE_LIST = 7;\r
Node.IS_WINDOW = 8;\r
Node.IS_DOCUMENT = 9;\r
Node.IS_IMAGE = 10;\r
\r
+\r
+Node.STATE_NO_RAW = 0; // new Node されたばかり\r
+Node.STATE_NO_PARENT = 1; // exist node._rawNode\r
+//Node.STATE_DIRTY = 2;\r
+Node.STATE_STAGED = 2; // exist _rawNode.parentNode\r
+Node.STATE_DESTROYED = 3;\r
+\r
+Node._useDocumentFragment = document.createDocumentFragment && ( !X.UA.IE || 6 <= X.UA.IE ) && document.createDocumentFragment();\r
+\r
Node._getType = function( v ){\r
if( v === '' ) return Node.IS_STRING;\r
if( !v ) return 0;\r
if( typeof v === 'string' ){\r
return '<' === v.charAt( 0 ) && v.charAt( v.length - 1 ) === '>' ? Node.IS_HTML_STRING : Node.IS_STRING;\r
};\r
- if( v.nodeType === 11 ) return Node.IS_DOC_FRAG;\r
+ //if( v.nodeType === 11 ) return Node.IS_DOC_FRAG;\r
return 0;\r
};\r
Node._getXNode = function( node ){\r
var uid;\r
- if( !node ) return;\r
- if( X.UA.IE && X.UA.IE < 5 ){\r
- uid = node.getAttribute( 'UID' );\r
- return uid && Node._chashe[ uid ];\r
+ switch( Node._getType( node ) ){\r
+ case Node.IS_XNODE :\r
+ case Node.IS_XNODE_LIST :\r
+ return node;\r
+ case Node.IS_RAW_HTML :\r
+ case Node.IS_RAW_TEXT :\r
+ case Node.IS_IMAGE :\r
+ if( X.UA.IE && X.UA.IE < 5 ){\r
+ uid = node.getAttribute( 'UID' );\r
+ return uid && Node._chashe[ uid ];\r
+ };\r
+ return node.UID && Node._chashe[ node.UID ];\r
+ case Node.IS_WINDOW :\r
+ return Node._window;\r
+ case Node.IS_DOCUMENT :\r
+ return Node._document;\r
};\r
- return node.UID && Node._chashe[ node.UID ];\r
};\r
\r
\r
return root._rawNode.createElement( 'p' ).tagName !== root._rawNode.createElement( 'P' ).tagName;\r
});\r
\r
-\r
-/* --------------------------------------\r
- * Dom Core 1\r
- */\r
-if( document.getElementById ){\r
- Node._dom1cleanUp = function( xnode ){\r
- var elm = xnode._rawNode,\r
- children = xnode._xnodes,\r
- childNodes, i, l, child, _child;\r
- if( elm && children && ( childNodes = elm.childNodes ) ){\r
- for( i = 0, l = children.length; i < l; ++i ){\r
- child = children[ i ];\r
- if( child.constructor === Node ) child = child._create( true );\r
- if( typeof child === 'string' ) child = document.createTextNode( child );\r
- if( ( _child = childNodes[ i ] ) !== child ){\r
- _child ?\r
- elm.insertBefore( child, _child ) :\r
- elm.appendChild( child );\r
- _child && elm.removeChild( _child );\r
- };\r
- };\r
- while( ( _child = childNodes[ i ] ) ){\r
- elm.removeChild( _child );\r
- };\r
- };\r
- }; \r
-};\r
-\r
Node._chashe = [];\r
Node.none = Node._chashe[ 0 ] = new Node();\r
Node._window = new Node( window ); // Node._chashe[ 1 ]\r
Node.root = null;// = Node._chashe[ 4 ] body\r
Node._systemNode = null;// = Node._chashe[ ? ]\r
\r
-/* --------------------------------------\r
- * Create\r
- */\r
-Node.prototype._create =\r
- // document.createElement of ie4 is only for OPTION & IMAGE.\r
- document.getElementById ? (function( isChild ){\r
- var tag = this._tag, node, frg;\r
-/*\r
- * http://d.hatena.ne.jp/uupaa/20080718/1216362040\r
- * DOM Rangeが使える環境(Firefox2+,Opera9+,Safari3+)なら、innerHTMLいらずで、ガーって書けます。\r
- * return document.createRange().createContextualFragment("<div><select><option></option></select></div>");\r
- * \r
- * ie7 以下では iframe の frameborder や、input name は、createElement 後に aetAttribute しても無視される\r
- */\r
-\r
- if( !( node = this._rawNode ) ){\r
- this._isNew = true;\r
- node = this._rawNode = (\r
- tag && X.UA.IE ?\r
- document.createElement( [\r
- '<', this._tag,\r
- ' UID="', this._uid, '"',\r
- this._id ? ' id="' + this._id + '"' : '',\r
- this._classText,\r
- ( this._attrUpdated ? ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ) : this._attrText ),\r
- this._styleText,\r
- '>' ].join( '' ) ) :\r
- tag ?\r
- document.createElement( tag ) :\r
- document.createTextNode( this._text ) );\r
- delete this._attrUpdated;\r
- };\r
- // fragument がある場合 children も足して\r
- // Mozilla: 1.0+, IE: 6.0+, Netscape: 2.0+, Safari: 1.0+, Opera: 7.0+\r
- if( !isChild && document.createDocumentFragment ){\r
- if( node.nodeType === 1 ){\r
- frg = document.createDocumentFragment();\r
- frg.appendChild( node );\r
- Node._dom1cleanUp( this );\r
- return frg;\r
- };\r
- };\r
- \r
- return node;\r
- }) :\r
- document.all ? (function( skipRemove, skipContainsDirty ){\r
- var html, attrs, attr, children, i, l, child, toName, noValue, name;\r
- if( this._xnodeType !== 1 ) return this._text;\r
- \r
- if( this._rawNode || this._ie4getRawNode() ){\r
- if( skipRemove ){\r
- this._beforeRemove();\r
- } else {\r
- // 追加する前に要素を抜く\r
- this.remove(); \r
- };\r
- if( !skipContainsDirty && !this._ie4containsDirty() ){\r
- return this._htmlText;\r
- };\r
- };\r
- html = [\r
- '<', this._tag, ' id=', ( this._id || ( 'ie4uid' + this._uid ) ),\r
- this._classText,\r
- ( this._attrUpdated ? ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ) : this._attrText ),\r
- this._styleText,\r
- '>' ];\r
- delete this._attrUpdated;\r
- \r
- if( ( children = this._xnodes ) && ( l = children.length ) ){\r
- for( i = 0; i < l; ++i ){\r
- html[ html.length ] = children[ i ]._create( true, true );\r
- };\r
- };\r
- html[ html.length ] = '<\/' + this._tag + '>';\r
- return html.join( '' );\r
- }) :\r
- (function(){});\r
+Node._reserveRemoval = [];\r
\r
-Node.prototype._afterCreate =\r
- ( document.getElementById ) ? (function( parent ){\r
- var _children = this._xnodes,\r
- node = this._rawNode,\r
- eChildren = node && node.nodeType === 1 && node.childNodes,\r
- attrs, p, _child, i, l;\r
- this.parent = parent;\r
- if( this._xnodeType !== 1 ) return this;\r
- if( this._isNew ){\r
- if( _children && !document.createDocumentFragment ){\r
- Node._dom1cleanUp( this ); // docFrg が使えない場合、doc 追加後に子を追加\r
- };\r
- if( !X.UA.IE ){\r
- node.UID = this._uid;\r
- if( this._id ) node.id = this._id;\r
- if( this._className ) node.className = this._className;\r
- // ie では createElement に <div class=...> HTML 文字列を渡すことができる\r
- // 動的に生成した iframe に後から frameborder 等を設定しても無視される ie7\r
- if( attrs = this._attrs ){\r
- for( p in attrs ){\r
- node[ p ] = attrs[ p ];\r
- };\r
- };\r
- node.style.cssText = this._cssText; \r
- };\r
- this._restoreEvent();// イベントの復帰\r
- delete this._isNew;\r
+if( !document.getElementById && document.all ){\r
+ Node.prototype._ie4getRawNode = function(){\r
+ var elm, uid;\r
+ if( elm = this._rawNode ) return elm;\r
+ if( this._id && ( elm = this._rawNode = document.all[ this._id ] ) ){\r
+ return elm;\r
};\r
- /*\r
- * elm.childNodes を this._xnodes にリンクさせる\r
- */\r
- if( _children ){\r
- for( i = 0, l = _children.length; i < l; ++i ){\r
- _child = _children[ i ];\r
- _child.constructor === Node ? _child._afterCreate( this ) : ( _children[ i ] = eChildren[ i ] );\r
- };\r
- } else\r
- if( eChildren && eChildren.length ){\r
- this._xnodes = [];\r
- this._xnodes.push.apply( this._xnodes, eChildren );\r
+ if( elm = this._rawNode = document.all[ 'ie4uid' + this._uid ] ){\r
+ if( this._id ) elm.setAttribute( 'id', this._id );\r
+ return elm;\r
};\r
- return this;\r
- }) :\r
- document.all ? (function( parent ){\r
- var elm,\r
- children = this._xnodes,\r
- child, i, l;\r
- this.parent = parent;\r
- delete this._ie4dirty;\r
- \r
- if( this._xnodeType !== 1 ) return this;\r
+ };\r
+};\r
\r
- delete this._rawNode;\r
- delete this._ie4dirtyChildren;\r
- \r
- if( children ){\r
- for( i = children.length; i; ){\r
- children[ --i ]._afterCreate( this );\r
- };\r
- };\r
- if( elm = this._ie4getRawNode() ){\r
- this._restoreEvent();// イベントの復帰\r
- elm.setAttribute( 'UID', '' + this._uid );\r
- };\r
- }) :\r
- (function(){});\r
\r
/* --------------------------------------\r
* Create\r
*/\r
Node.prototype.create = function( tag, opt_attrs, opt_css ){\r
- var elm, xnode;\r
+ var xnode;\r
if( this._xnodeType !== 1 ) return;\r
if( !this._xnodes ) this._xnodes = [];\r
\r
- elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
- \r
- if( elm && !Node.skipCreate ){\r
- if( document.getElementById ){\r
- // ie では iframe の frameborder が無視されるので、<iframe class=> を渡す\r
- elm.appendChild( document.createElement( tag ) );\r
- xnode = new Node( elm.lastChild );\r
- opt_attrs && xnode.attr( opt_attrs );\r
- opt_css && xnode[ X.Type.isString( opt_css ) ? 'cssText' : 'css' ]( opt_css );\r
- } else\r
- if( document.all ){\r
- Node._newByTag = true;\r
- xnode = new Node( tag, opt_attrs, opt_css );\r
- // opt_attrs && xnode.attr( opt_attrs );\r
- elm.insertAdjacentHTML( 'BeforeEnd', xnode._create() );\r
- xnode._rawNode = elm.children[ elm.children.length - 1 ];\r
- } else {\r
- \r
- };\r
- } else {\r
- Node._newByTag = true;\r
- xnode = new Node( tag, opt_attrs, opt_css );\r
- };\r
+ Node._newByTag = true;\r
+ xnode = new Node( tag, opt_attrs, opt_css );\r
xnode.parent = this;\r
+ \r
+ this._reserveUpdate();\r
this._xnodes[ this._xnodes.length ] = xnode;\r
return xnode;\r
};\r
* CreateText\r
*/\r
Node.prototype.createText = function( text ){\r
- var elm, xnode;\r
+ var xnode;\r
if( this._xnodeType !== 1 ) return;\r
if( !this._xnodes ) this._xnodes = [];\r
\r
- elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
- \r
- if( elm && !Node.skipCreate ){\r
- if( document.createTextNode ){\r
- elm.appendChild( document.createTextNode( text ) );\r
- xnode = new Node( elm.lastChild );\r
- } else\r
- if( document.all ){\r
- elm.insertAdjacentText( 'BeforeEnd', text );\r
- Node._newByText = true;\r
- xnode = new Node( text );\r
- } else {\r
- \r
- };\r
- } else {\r
- Node._newByText = true;\r
- xnode = new Node( text );\r
- };\r
+ Node._newByText = true;\r
+ xnode = new Node( text );\r
xnode.parent = this;\r
+ \r
+ this._reserveUpdate();\r
this._xnodes[ this._xnodes.length ] = xnode;\r
return xnode;\r
};\r
* http://d.hatena.ne.jp/uupaa/20100508/1273299874\r
*/\r
Node.prototype.clone = function( opt_clone_children ){\r
- var xnode, elm;\r
+ var xnode, xnodes, i, l;\r
switch( this._xnodeType ){\r
case 1 :\r
- if( X.UA.IE && X.UA.IE < 5 ){\r
- \r
- } else\r
- if( X.UA.IE && 5 <= X.UA.IE && X.UA.IE < 10 ){\r
- Node._newByTag = true;\r
- xnode = new Node( this._tag, this._attrs, this._css );\r
- xnode.className( this.className() );\r
- if( opt_clone_children ){\r
- \r
+ Node._newByTag = true;\r
+ xnode = new Node( this._tag, X.cloneObject( this._attrs ), X.cloneObject( this._css ) );\r
+ xnode.className( this._className );\r
+ if( opt_clone_children && ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
+ for( i = 0; i < l; ++i ){\r
+ xnode.append( xnodes[ i ].clone( true ) );\r
};\r
- } else\r
- if( elm = this.rawNode ){\r
- xnode = new Node( elm.cloneNode( !!opt_clone_children ) );\r
};\r
-\r
return xnode;\r
case 3 :\r
Node._newByText = true;\r
* HtmlElement の場合は内部使用専用 そのため event の破棄等しない\r
*/\r
Node.prototype.append = function( v ){\r
- var elm, i, l, children, frg;\r
+ var i, l, xnodes, frg;\r
if( this._xnodeType !== 1 ) return;\r
\r
if( 1 < ( l = arguments.length ) ){\r
- if( document.createDocumentFragment && this._rawNode ){\r
- frg = document.createDocumentFragment();\r
- for( i = 0; i < l; ++i ){\r
- v = arguments[ i ];\r
- v = v.constructor === Node ? v : new Node( v );\r
- frg.appendChild( v._create() );\r
- this._xnodes[ this._xnodes.length ] = v;\r
- v._afterCreate( this );\r
- };\r
- this._rawNode.appendChild( frg );\r
- return this;\r
- } else {\r
- for( i = 0; i < l; ++i ){\r
- this.append( arguments[ i ] );\r
- };\r
+ for( i = 0; i < l; ++i ){\r
+ this.append( arguments[ i ] );\r
};\r
return this;\r
};\r
\r
- if( !this._xnodes ) this._xnodes = [];\r
+ if( !( xnodes = this._xnodes ) ) this._xnodes = xnodes = [];\r
\r
- elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
switch( Node._getType( v ) ){\r
case Node.IS_RAW_HTML :\r
case Node.IS_RAW_TEXT :\r
- if( elm ){\r
- if( document.getElementById ){\r
- elm.appendChild( v );\r
- } else\r
- if( document.all ){\r
- elm.insertAdjacentHTML( 'BeforeEnd', v.outerHTML );\r
- v = elm.children[ elm.children.length - 1 ];\r
- } else {\r
- \r
- };\r
- };\r
- this._xnodes[ this._xnodes.length ] = new Node( v );\r
+ v = new Node( v );\r
break;\r
case Node.IS_HTML_STRING :\r
case Node.IS_STRING :\r
- this.append( X.Dom.parse( v, true ) );\r
- break;\r
+ return this.append( X.Dom.parse( v, true ) );\r
case Node.IS_XNODE :\r
- if( v === Node.none ) return this;\r
+ if( v._xnodeType !== 1 && v._xnodeType !== 3 ) return this;\r
// 親の xnodes から v を消す\r
- v.parent && ( i = v.parent._xnodes.indexOf( v ) ) !== -1 && v.parent._xnodes.splice( i, 1 );\r
- if( elm ){\r
- if( document.getElementById ){\r
- elm.appendChild( v._create() );\r
- v._afterCreate( this );\r
- } else\r
- if( document.all ){\r
- elm.insertAdjacentHTML( 'BeforeEnd', v._create() );\r
- v._afterCreate( this );\r
- } else {\r
- \r
- };\r
+ if( v.parent ){\r
+ v.parent._xnodes.splice( v.parent._xnodes.indexOf( v ), 1 );\r
+ // ie4\r
+ !document.getElementById && document.all && v.remove();\r
+ } else\r
+ if( ( i = Node._reserveRemoval.indexOf( v ) ) !== -1 ){\r
+ if( v._destroyed ) alert( 'xnode already destroyed!' );\r
+ Node._reserveRemoval.splice( i, 1 );\r
};\r
- this._xnodes[ this._xnodes.length ] = v;\r
+ default :\r
+ return this;\r
};\r
+\r
+ this._reserveUpdate();\r
+ v.parent = this;\r
+ v._state = Node.STATE_NO_PARENT;\r
+ xnodes[ xnodes.length ] = v;\r
return this;\r
};\r
\r
\r
Node.prototype.appendAt = function( start, v ){\r
- var children, l, elm, i, prev, next;\r
+ var xnodes, l, i;\r
\r
if( this._xnodeType !== 1 ) return this;\r
\r
- if( !( children = this._xnodes ) ) children = this._xnodes = [];\r
+ if( !( xnodes = this._xnodes ) ) xnodes = this._xnodes = [];\r
\r
l = arguments.length;\r
- if( children.length <= start ){\r
+ if( xnodes.length <= start ){\r
if( l === 2 ) return this.append( v );\r
v = [];\r
for( ; 1 < l; ){\r
};\r
if( start < 0 ) start = 0;\r
if( 2 < l ){\r
- if( document.createDocumentFragment && ( elm = this._rawNode ) ){\r
- var frg = document.createDocumentFragment();\r
- for( i = 0; i < l; ++i ){\r
- v = arguments[ i ];\r
- v = v.constructor === Node ? v : new Node( v );\r
- frg.appendChild( v._create() );\r
- children.splice( start + i, 0, v );\r
- v._afterCreate( this );\r
- };\r
- elm.insertBefore( frg, elm.childNodes[ start ] );\r
- return this;\r
- };\r
for( ; l; ){\r
this.appendAt( start, arguments[ --l ] );\r
};\r
return this;\r
};\r
- \r
- if( !this.parent ){\r
- children.splice( start, 0, v );\r
- return this;\r
- };\r
- elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
+\r
switch( Node._getType( v ) ){\r
case Node.IS_RAW_HTML :\r
case Node.IS_RAW_TEXT :\r
- if( elm ){\r
- if( document.getElementById ){\r
- elm.insertBefore( v, elm.childNodes[ start ] );\r
- } else\r
- if( document.all ){\r
- if( start === 0 ){\r
- elm.insertAdjacentHTML( 'AfterBegin', v.outerHTML );\r
- v = elm.children[ 0 ];\r
- } else\r
- if( ( next = children[ start ] ) && typeof next !== 'string' && next._xnodeType !== 3 &&\r
- ( next = ( next._ie4getRawNode ? next._ie4getRawNode() : next ) ) ){\r
- next.insertAdjacentHTML( 'BeforeBegin', v.outerHTML );\r
- v = elm.children[ ( Array.prototype.indexOf.call( elm.children, next ) ) - 1 ];\r
- } else\r
- if( 0 < start && ( prev = children[ start - 1 ] ) && typeof prev !== 'string' && prev._xnodeType !== 3 &&\r
- ( prev = ( prev._ie4getRawNode ? prev._ie4getRawNode() : prev ) ) ){\r
- prev.insertAdjacentHTML( 'AfterEnd', v.outerHTML );\r
- v = elm.children[ ( Array.prototype.indexOf.call( elm.children, prev ) ) + 1 ];\r
- } else {\r
- this._ie4reserveUpdate( v );// テキストノードの間に入れる場合!\r
- };\r
- } else {\r
- \r
- };\r
- children.splice( start, 0, v );\r
- } else {\r
- children.splice( start, 0, v );\r
- };\r
+ v = new Node( v );\r
break;\r
case Node.IS_HTML_STRING :\r
case Node.IS_STRING :\r
v = X.Dom.parse( v, true );\r
- if( elm ){\r
- for( i = v.length; i; ){\r
- this.appendAt( start, v[ --i ] );\r
- };\r
- } else\r
- if( v.length ){\r
- children.push.apply( children, v );\r
+ for( i = v.length; i; ){\r
+ this.appendAt( start, v[ --i ] );\r
};\r
- break;\r
+ return this;\r
case Node.IS_XNODE :\r
- if( v === Node.none ) return this;\r
+ if( v._xnodeType !== 1 && v._xnodeType !== 3 ) return this;\r
// 親の xnodes から v を消す\r
- v.parent && ( i = v.parent._xnodes.indexOf( v ) ) !== -1 && v.parent._xnodes.splice( i, 1 );\r
- if( elm ){\r
- if( document.getElementById ){\r
- elm.insertBefore( v._create(), elm.childNodes[ start ] );\r
- v._afterCreate( this );\r
- } else\r
- if( document.all ){\r
- this._ie4reserveUpdate( v );\r
- } else {\r
- \r
- };\r
+ if( v.parent ){\r
+ v.parent._xnodes.splice( v.parent._xnodes.indexOf( v ), 1 );\r
+ // ie4\r
+ !document.getElementById && document.all && v.remove();\r
+ } else\r
+ if( ( i = Node._reserveRemoval.indexOf( v ) ) !== -1 ){\r
+ if( v._destroyed ) alert( 'xnode already destroyed!' );\r
+ Node._reserveRemoval.splice( i, 1 );\r
};\r
- children.splice( start, 0, v );\r
+ break;\r
+ default :\r
+ return this;\r
};\r
+\r
+ this._reserveUpdate();\r
+ v.parent = this;\r
+ v._state = Node.STATE_NO_PARENT;\r
+ this._xnodes.splice( start, 0, v );\r
return this;\r
};\r
\r
* Remove\r
*/\r
Node.prototype.remove = function(){\r
- var parent = this.parent, elm;\r
+ var parent = this.parent;\r
\r
if( !parent ) return this;\r
- if( document.getElementById ){\r
- if( this._rawNode ){\r
- this._xnodeType === 1 && this._beforeRemove();\r
- parent._rawNode.removeChild( this._rawNode );\r
- };\r
- } else\r
- if( document.all ){\r
- delete this._ie4dirty;\r
- delete this._ie4dirtyChildren;\r
- if( this._xnodeType === 1 ){\r
- this._beforeRemove();\r
- if( elm = this._ie4getRawNode() ){\r
- elm.outerHTML = '';\r
- };\r
- } else {\r
- parent._beforeRemove(); //??\r
- parent._ie4reserveUpdate();\r
- };\r
- } else {\r
- \r
- };\r
\r
+ this._state = Node.STATE_NO_PARENT;\r
parent._xnodes.splice( parent._xnodes.indexOf( this ), 1 );\r
+ Node._reserveRemoval[ Node._reserveRemoval.length ] = this;\r
+ parent._reserveUpdate();\r
delete this.parent;\r
return this;\r
};\r
\r
-Node.prototype._beforeRemove = \r
- document.getElementById ?\r
- ( function(){\r
- var elm = this._rawNode, children,\r
- child, i, l;\r
- if( !elm ) return;\r
- this._migrateEvent();// イベントの退避\r
- if( children = this._xnodes ){\r
- for( i = 0, l = children.length; i < l; ++i ){\r
- child = children[ i ];\r
- child._xnodeType === 1 && child._beforeRemove();\r
- };\r
- };\r
- }) :\r
- document.all ? \r
- ( function(){\r
- var elm = this._ie4getRawNode(),\r
- children, i, l;\r
- if( children = this._xnodes ){\r
- for( i = 0, l = children.length; i < l; ++i ){\r
- children[ i ]._beforeRemove();\r
- }; \r
- };\r
- if( !elm ) return;\r
- this._migrateEvent();// イベントの退避\r
- this._htmlText = elm.outerHTML;\r
- elm.removeAttribute( 'id' );\r
- }) :\r
- (function(){});\r
-\r
-Node.prototype.empty =\r
- document.getElementById ?\r
- ( function(){\r
- var elm = this._rawNode, children,\r
- child, i, l;\r
- if( children = this._xnodes ){\r
- for( i = 0, l = children.length; i < l; ++i ){\r
- children[ i ].destroy();\r
- };\r
- children.length = 0;\r
- };\r
- if( elm ) elm.innerHTML = '';\r
- return this;\r
- }) :\r
- document.all ? \r
- ( function(){\r
- var elm = this._ie4getRawNode(),\r
- children, i, l;\r
- if( children = this._xnodes ){\r
- for( i = 0, l = children.length; i < l; ++i ){\r
- children[ i ].destroy();\r
- };\r
- children.length = 0;\r
- };\r
- if( elm ) elm.innerHTML = '';\r
- return this;\r
- }) :\r
- (function(){});\r
-\r
-/* --------------------------------------\r
- * destory\r
- */\r
-Node.prototype.destroy = function(){\r
- var elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode,\r
- children = this._xnodes, i, l;\r
- \r
- if( children ){\r
- for( i = 0, l = children.length; i < l; ++i ){\r
- children[ i ].destroy();\r
+Node.prototype.empty = function(){\r
+ var xnodes = this._xnodes, child, i, l;\r
+ if( xnodes && ( l = xnodes.length ) ){\r
+ for( i = 0; i < l; ++i ){\r
+ xnodes[ i ].destroy();\r
};\r
- children.length = 0;\r
- };\r
- this._xnodeType === 1 && this.unlisten(); // イベントの退避\r
- if( elm ){\r
- this._xnodeType === 1 && ( elm.innerHTML = '' );\r
- // stop()\r
- // remove() empty()\r
- \r
- document.getElementById && this.parent._rawNode.removeChild( elm );\r
+ xnodes.length = 0;\r
};\r
- delete Node._chashe[ this._uid ];\r
- this.kill();\r
+ return this;\r
};\r
\r
/* --------------------------------------\r
- * for ie4\r
+ * destory\r
*/\r
-if( !document.getElementById && document.all ){\r
-\r
- Node.prototype._ie4getRawNode = function(){\r
- var elm, uid;\r
- if( elm = this._rawNode ) return elm;\r
- if( this._id && ( elm = this._rawNode = document.all[ this._id ] ) ){\r
- return elm;\r
- };\r
- if( elm = this._rawNode = document.all[ 'ie4uid' + this._uid ] ){\r
- if( this._id ) elm.setAttribute( 'id', this._id );\r
- return elm;\r
- };\r
- };\r
+Node.prototype.destroy = function( isChild ){\r
+ var xnodes = this._xnodes, i;\r
\r
- Node.prototype._ie4reserveUpdate = function( child ){\r
- var root = Node.root;\r
- child && ( child._ie4dirty = true );\r
- this._ie4dirtyChildren = true;\r
- if( root._ie4reserved === true ) return;\r
- root._ie4reserved = true;\r
- X.Timer.once( 1, root, root._ie4startUpdate );\r
- };\r
- \r
- Node.prototype._ie4startUpdate = function(){\r
- if( this._ie4reserved !== true ) return;\r
- delete this._ie4reserved;\r
- if( !this._xnodes ) return;\r
- this._ie4commitUpdate()._ie4afterUpdate();\r
- };\r
- \r
- Node.prototype._ie4commitUpdate = function(){\r
- var children = this._xnodes,\r
- i, l, html;\r
- if( !this._ie4dirtyChildren ){\r
- if( children && ( l = children.length ) ){\r
- for( i = 0; i < l; ++i ){\r
- children[ i ]._ie4commitUpdate();\r
- }; \r
- };\r
- return this;\r
- };\r
- html = [];\r
- if( children && ( l = children.length ) ){\r
- for( i = 0; i < l; ++i ){\r
- html[ html.length ] = children[ i ]._create( true );\r
- }; \r
- };\r
- this._rawNode.innerHTML = html.join( '' );\r
- return this;\r
- };\r
+ if( this._destroyed ) return;\r
\r
- Node.prototype._ie4afterUpdate = function(){\r
- var children = this._xnodes,\r
- i, l;\r
- if( !this._ie4dirtyChildren ){\r
- if( children && ( l = children.length ) ){\r
- for( i = 0; i < l; ++i ){\r
- children[ i ]._ie4afterUpdate();\r
- }; \r
- };\r
- return this;\r
- };\r
- if( children && ( l = children.length ) ){\r
- for( i = 0; i < l; ++i ){\r
- children[ i ]._afterCreate( this );\r
- }; \r
+ if( xnodes && ( i = xnodes.length ) ){\r
+ for( ; i; ){\r
+ xnodes[ --i ].destroy( true );\r
};\r
- delete this._ie4dirtyChildren;\r
+ xnodes.length = 0;\r
};\r
+ this.unlisten(); // イベントの退避\r
+\r
+ delete Node._chashe[ this._uid ];\r
\r
- Node.prototype._ie4containsDirty = function(){\r
- var children, i;\r
- if( this._xnodeType !== 1 ) return;\r
- if( this._ie4dirtyChildren || this._ie4dirty ) return true;\r
- if( !( children = this._xnodes ) || !( i = children.length ) ) return;\r
- for( ; i; ){\r
- if( children[ --i ]._ie4containsDirty() ) return true;\r
- };\r
+ if( this._rawNode && this._rawNode.parentNode && this._rawNode.parentNode.tagName ){\r
+ this.remove();\r
+ this._state = Node.STATE_DESTROYED;\r
+ this._destroyed = true; // state \r
+ } else {\r
+ this.parent._xnodes.splice( this.parent._xnodes.indexOf( this ), 1 );\r
+ !isChild && this._actualRemove();\r
+ this.kill();\r
};\r
};\r
\r
+\r
+\r
/* --------------------------------------\r
* contains\r
*/\r
Node.prototype.contains = function( v ){\r
- var node, children, i;\r
+ var node, xnodes, i;\r
if( !v || !this.parent || this._xnodeType !== -1 ) return false;\r
// contains ie4+\r
if( document.contains ){\r
//if( document.compareDocumentPosition ){\r
// \r
//};\r
- children = this._xnodes;\r
- if( children.indexOf( v ) !== -1 ) return true;\r
+ xnodes = this._xnodes;\r
+ if( xnodes.indexOf( v ) !== -1 ) return true;\r
if( ( node = this._rawNode ) && node === v.parentNode ) return false;\r
- for( i = children.length; i; ){\r
- if( children[ --i ].contains( v ) ) return true;\r
+ for( i = xnodes.length; i; ){\r
+ if( xnodes[ --i ].contains( v ) ) return true;\r
};\r
return false;\r
};\r
* getChild\r
*/\r
Node.prototype.getChildAt = function( index ){\r
- var children = this._xnodes,\r
- elm, childNodes, child, xnode;\r
- if( this._xnodeType !== 1 || index < 0 ) return;\r
- if( children.length <= index ) return;\r
- child = children[ index ];\r
- if( child.constructor === Node ) return child;\r
- xnode = new Node( child );\r
- xnode.parent = this;\r
- return children[ index ] = xnode;\r
+ var xnodes = this._xnodes;\r
+ if( this._xnodeType !== 1 || index < 0 || !xnodes || xnodes.length <= index ) return; //?\r
+ return xnodes[ index ];\r
};\r
\r
\r
*/\r
\r
Node.prototype.prevNode = function(){\r
- var parent = this.parent, children, index;\r
+ var parent = this.parent, xnodes, index;\r
if( !parent ) return;\r
- children = parent._xnodes;\r
- index = children.indexOf( this );\r
- if( 0 < index ) return children[ index - 1 ];\r
+ xnodes = parent._xnodes;\r
+ index = xnodes.indexOf( this );\r
+ if( 0 < index ) return xnodes[ index - 1 ];\r
};\r
Node.prototype.nextNode = function(){\r
- var parent = this.parent, children, index;\r
+ var parent = this.parent, xnodes, index;\r
if( !parent ) return;\r
- children = parent._xnodes;\r
- index = children.indexOf( this );\r
- if( index !== -1 && index + 1 < children.length ) return children[ index + 1 ];\r
+ xnodes = parent._xnodes;\r
+ index = xnodes.indexOf( this );\r
+ if( index + 1 < xnodes.length ) return xnodes[ index + 1 ];\r
};\r
Node.prototype.firstChild = function(){\r
return this.getChildAt( 0 );\r
Node.prototype.className = function( v ){\r
var node;\r
// getter\r
- if( typeof v !== 'string' ) return this._className;\r
+ if( v === undefined ) return this._className;\r
// setter\r
if( this._className === v ) return this;\r
- if( !v ) delete this._className;\r
- node = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;\r
- if( node ) node.className = v;\r
- this._className = v;\r
- this._classText = ' class="' + v + '" ';\r
+ if( !v || typeof v !== 'string' ){\r
+ delete this._className;\r
+ } else {\r
+ this._className = v; \r
+ };\r
+ this._dirty |= X.Dom.Dirty.CLASSNAME;\r
return this;\r
};\r
-Node.prototype.addClass = function(){\r
- \r
+Node.prototype.addClass = function( v ){\r
+ var names = v.split( ' ' ),\r
+ i = names.length,\r
+ name;\r
+ v = '';\r
+ for( ; i; ){\r
+ name = names[ --i ];\r
+ if( !name ) continue;\r
+ !this.hasClass( name ) && ( v += ( v ? ' ' : '' ) + name );\r
+ };\r
+ return v ? his.className( this._className + ( this._className ? ' ' : '' ) + v ) : this;\r
};\r
-Node.prototype.removeClass = function(){\r
- \r
+Node.prototype.removeClass = function( v ){\r
+ var _ = ' ',\r
+ className = this._className,\r
+ names = v.split( ' ' ),\r
+ classNames, i, f;\r
+ if( !className ) return this;\r
+ for( classNames = className.split( _ ), i = classNames.length; i; ){\r
+ className = classNames[ --i ];\r
+ for( j = names.length; j; ){\r
+ if( className === names[ --j ] ){\r
+ classNames.splice( i, 1 );\r
+ names.splice( j, 1 );\r
+ f = true;\r
+ break;\r
+ };\r
+ };\r
+ };\r
+ return f ? this.className( classNames.join( ' ' ) ) : this;\r
};\r
-Node.prototype.toggleClass = function(){\r
- \r
+Node.prototype.toggleClass = function( v ){\r
+\r
};\r
-Node.prototype.hasClass = function( className ){\r
+Node.prototype.hasClass = function( v ){\r
var _ = ' ',\r
- _className = this._className, i, name;\r
- if( _className === className ) return true;\r
- if( !_className ) return false;\r
+ className = this._className,\r
+ i, name;\r
+ if( className === v ) return true;\r
+ if( !className ) return false;\r
\r
- _className = _ + _className + _;\r
- if( _className.indexOf( _ + className + _ ) !== -1 ) return true; // lucky hit\r
+ className = _ + className + _;\r
+ if( className.indexOf( _ + v + _ ) !== -1 ) return true; // lucky hit\r
\r
- for( className = className.split( _ ), i = className.length; i; ){\r
- name = className[ --i ];\r
+ for( v = v.split( _ ), i = v.length; i; ){\r
+ name = v[ --i ];\r
if( name === '' ) continue;\r
- if( _className.indexOf( _ + name + _ ) === -1 ) return false;\r
+ if( className.indexOf( _ + name + _ ) === -1 ) return false;\r
};\r
return true;\r
};\r
/* --------------------------------------\r
* html, text\r
*/\r
-Node.prototype.html = function( html ){\r
+Node.prototype.html = function( html, opt_wrap ){\r
+ var xnodes, n, i, l;\r
+ // setter\r
if( html ){\r
if( this._xnodeType === 3 ){\r
- this._text = html;\r
- if( this._rawNode ) this._rawNode.data = html;\r
+ if( this._text !== html ){\r
+ this._text = html;\r
+ this.parent && this._reserveUpdate();\r
+ this._dirty |= X.Dom.Dirty.CONTENT;\r
+ };\r
return this;\r
};\r
- return this.empty().append.call( this, X.Dom.parse( html, true ) );\r
+ return this.empty().append.apply( this, X.Dom.parse( html, true ) );\r
+ };\r
+ // getter\r
+ if( this._xnodeType === 3 ){\r
+ return this._text;\r
};\r
- // if dirty\r
- return this._rawNode ? this._rawNode.innerHTML : '';\r
+ \r
+ if( this._dirty & X.Dom.Dirty.CSS && !( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
+ delete this._cssText;\r
+ };\r
+ html = !opt_wrap ? [] : [\r
+ '<', this._tag,\r
+ this._id ? ' id=' + this._id : '',\r
+ this._className ? ' class="' + this._className + '"' : '',\r
+ this._attrText || ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ),\r
+ this._cssText ? ' style="' + this._cssText + '"' : '',\r
+ '>' ];\r
+ \r
+ n = html.length;\r
+ if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
+ for( i = 0; i < l; ++i ){\r
+ html[ n ] = xnodes[ i ].html( undefined, true );\r
+ ++n;\r
+ };\r
+ };\r
+ !opt_wrap || X.Dom.DTD.EMPTY[ this._tag.toLowerCase() ] || ( html[ n ] = '<\/' + this._tag + '>' );\r
+\r
+ return html.join( '' );\r
};\r
\r
Node.prototype.text = function( text ){\r
+ var xnodes, n, i;\r
// setter\r
if( text ){\r
if( this._xnodeType === 3 ){\r
- this._text = text;\r
- if( this._rawNode ) this._rawNode.data = text;\r
+ if( this._text !== text ){\r
+ this._text = text;\r
+ this.parent && this._reserveUpdate();\r
+ this._dirty |= X.Dom.Dirty.CONTENT;\r
+ };\r
return this;\r
};\r
this.empty().createText( text );\r
};\r
// getter\r
if( this._xnodeType === 1 ){\r
- //\r
+ if( ( xnodes = this._xnodes ) && ( i = xnodes.length ) ){\r
+ for( text = [], n = -1; i; ){\r
+ text[ ++n ] = xnodes[ --i ].text();\r
+ };\r
+ return text.join( '' );\r
+ };\r
+ return '';\r
};\r
return this._text;\r
};\r
\r
+/* --------------------------------------\r
+ * Async commit update\r
+ * \r
+ * state:\r
+ * 0 : no_rawnode\r
+ * 1 : not_added\r
+ * 3 : dirty\r
+ * 4 : clean\r
+ * \r
+ * remove :\r
+ * root._reserveRemoval = [] に追加。commitUpdate で remove して state は not_added\r
+ * add :\r
+ * root._reserveRemoval にいたら消す, new_parent._xnodes に挿入 steta は not_added にして commitUpdate を待つ\r
+ */\r
+ \r
+Node.prototype._reserveUpdate = function( child ){\r
+ var root = Node.root;\r
+ //if( !root ) return;\r
+ //child && ( child._dirty = true );\r
+ if( root && !root._updateReserved ) root._updateReserved = X.Timer.requestFrame( root, root._startUpdate );\r
+};\r
+\r
+Node.prototype._startUpdate = function(){\r
+ var removal, i, xnode, tmp;\r
+ \r
+ if( this._updateReserved ){\r
+ //X.Timer.cancelFrame( this._updateReserved );\r
+ delete this._updateReserved;\r
+ } else {\r
+ return;\r
+ };\r
+\r
+ removal = Node._reserveRemoval;\r
+ i = removal.length;\r
+ \r
+ tmp = this._rawNode.style.visibility;\r
+ //this._rawNode.style.visibility = 'hidden';\r
+ \r
+ for( ; i; ){\r
+ xnode = removal[ --i ];\r
+ xnode._actualRemove();\r
+ xnode._destroyed && xnode.kill();\r
+ };\r
+ this._commitUpdate();\r
+ \r
+ //this._rawNode.style.visibility = tmp;\r
+};\r
+\r
+Node.prototype._commitUpdate =\r
+ document.getElementById ?\r
+ ( function( parentElement, nextElement ){\r
+ var elm = this._rawNode,\r
+ xnodes, l, i, next, k, v;\r
+\r
+ if( !elm ){\r
+ nextElement ?\r
+ parentElement.insertBefore( this._actualCreate(), nextElement ) :\r
+ parentElement.appendChild( this._actualCreate() );\r
+ this._afterActualCreate();\r
+ return this._rawNode;\r
+ } else \r
+ if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
+ for( ; l; ){\r
+ next = xnodes[ --l ]._commitUpdate( elm, next );\r
+ };\r
+ };\r
+\r
+ // textNode\r
+ if( this._dirty & X.Dom.Dirty.CONTENT ) elm.data = X.Dom.chrReferanceTo( this._text );\r
+ // className\r
+ if( this._dirty & X.Dom.Dirty.CLASSNAME ) elm.className = this._className;\r
+ // style\r
+ if( this._dirty & X.Dom.Dirty.CSS ){\r
+ if( this._cssText || ( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
+ elm.style.cssText = this._cssText;\r
+ } else {\r
+ elm.removeAttribute( 'style' );\r
+ delete this._cssText;\r
+ };\r
+ };\r
+ // attr\r
+ if( this._newAttrs ){\r
+ for( k in this._newAttrs ){\r
+ ( v = this._newAttrs[ k ] ) === undefined ?\r
+ elm.removeAttribute( k ) :\r
+ ( elm[ k ] = v );\r
+ };\r
+ delete this._newAttrs;\r
+ };\r
+ \r
+ delete this._dirty;\r
+ \r
+ return elm;\r
+ }) :\r
+ document.all ? \r
+ ( function( parentElement, prevElement ){\r
+ var elm = this._rawNode || this._ie4getRawNode(),\r
+ xnodes = this._xnodes,\r
+ l = xnodes && xnodes.length,\r
+ i, html, elm, child, prev, k, v;\r
+\r
+ if( !elm ){\r
+ prevElement ?\r
+ prevElement.insertAdjacentText( 'AfterEnd', this._actualCreate() ) :\r
+ parentElement.insertAdjacentText( 'BeforeEnd', this._actualCreate() );\r
+ this._afterActualCreate();\r
+ return this._rawNode || this._ie4getRawNode();\r
+ } else\r
+ if( this._dirty | X.Dom.Dirty.IE4_TEXTNODE_FIX ){\r
+ html = [];\r
+ for( i = 0; i < l; ++i ){\r
+ html[ i ] = xnodes[ i ]._actualCreate();\r
+ };\r
+ elm.innerHTML = html.join( '' );\r
+ for( i = 0; i < l; ++i ){\r
+ xnodes[ i ]._afterActualCreate();\r
+ };\r
+ } else \r
+ if( l ){\r
+ for( i = 0; i < l; ++i ){\r
+ prev = xnodes[ i ]._commitUpdate( elm, prev );\r
+ };\r
+ };\r
+\r
+ // fake textNode\r
+ if( this._dirty & X.Dom.Dirty.CONTENT ) elm.innerHTML = this._text;\r
+ // className\r
+ if( this._dirty & X.Dom.Dirty.CLASSNAME ) elm.className = this._className;\r
+ // style\r
+ if( this._dirty & X.Dom.Dirty.CSS ){\r
+ if( this._cssText || ( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
+ elm.style.cssText = this._cssText;\r
+ } else {\r
+ elm.removeAttribute( 'style' );\r
+ delete this._cssText;\r
+ };\r
+ };\r
+ // attr\r
+ if( this._newAttrs ){\r
+ for( k in this._newAttrs ){\r
+ ( v = this._newAttrs[ k ] ) === undefined ?\r
+ elm.removeAttribute( k ) :\r
+ elm.setAttribute( k, v );\r
+ };\r
+ delete this._newAttrs;\r
+ };\r
+ \r
+ delete this._dirty;\r
+ \r
+ return elm;\r
+ }) :\r
+ (function(){});\r
+\r
+/* --------------------------------------\r
+ * Create\r
+ * \r
+ * http://d.hatena.ne.jp/uupaa/20080718/1216362040\r
+ * DOM Rangeが使える環境(Firefox2+,Opera9+,Safari3+)なら、innerHTMLいらずで、ガーって書けます。\r
+ * return document.createRange().createContextualFragment("<div><select><option></option></select></div>");\r
+ * insertAdjacentHTML\r
+ * \r
+ * ie7 以下では iframe の frameborder や、input name は、createElement 後に aetAttribute しても無視される\r
+ * \r
+ * fragument がある場合 children も足して\r
+ * Mozilla: 1.0+, IE: 6.0+, Netscape: 2.0+, Safari: 1.0+, Opera: 7.0+\r
+ * ie6 大丈夫?fragment の場合リークしないか?チェックが必要\r
+ * http://msdn.microsoft.com/ja-jp/library/bb250448%28v=vs.85%29.aspx\r
+ * \r
+ * document.createElement of ie4 is only for OPTION & IMAGE.\r
+ */\r
+Node.prototype._actualCreate =\r
+ document.getElementById ? (function( isChild ){\r
+ var elm = this._rawNode,\r
+ xnodes, frg, i, l;\r
+ \r
+ if( this._xnodeType === 3 ){\r
+ return elm || ( this._rawNode = document.createTextNode( X.Dom.chrReferanceTo( this._text ) ) );\r
+ };\r
+ \r
+ if( !elm ){\r
+ if( this._dirty & X.Dom.Dirty.CSS && !( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
+ delete this._cssText;\r
+ };\r
+ this._isNew = true;\r
+ this._rawNode = elm =\r
+ X.UA.IE ?\r
+ document.createElement( [\r
+ '<', this._tag,\r
+ ' UID="', this._uid, '"',\r
+ this._id ? ' id="' + this._id + '"' : '',\r
+ this._className ? ' class="' + this._className + '"' : '',\r
+ this._attrText || ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ),\r
+ this._cssText ? ' style="' + this._cssText + '"' : '',\r
+ '>' ].join( '' ) ):\r
+ document.createElement( this._tag );\r
+ };\r
+ if( Node._useDocumentFragment ){\r
+ if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
+ !isChild && ( frg = Node._useDocumentFragment ).appendChild( elm );\r
+ for( i = 0; i < l; ++i ){\r
+ elm.appendChild( xnodes[ i ]._actualCreate( true ) );\r
+ };\r
+ return frg || elm;\r
+ };\r
+ };\r
+ \r
+ return elm;\r
+ }) :\r
+ document.all ? (function(){\r
+ var uid = this._uid,\r
+ html, xnodes, n, i, l;\r
+ \r
+ if( this._xnodeType === 3 ){\r
+ html = [ '<font id=ie4uid', uid, ' UID=', uid, '>', this._text, '</font>' ];// fake textNode\r
+ } else {\r
+ if( this._dirty & X.Dom.Dirty.CSS && !( this._cssText = X.Dom.Style.objToCssText( this._css ) ) ){\r
+ delete this._cssText;\r
+ };\r
+ html = [\r
+ '<', this._tag, ' id=', ( this._id || ( 'ie4uid' + uid ) ), ' UID=', uid,\r
+ this._className ? ' class="' + this._className + '"' : '',\r
+ this._attrText || ( this._attrText = X.Dom.Attr.objToAttrText( this._attrs ) ),\r
+ this._cssText ? ' style="' + this._cssText + '"' : '',\r
+ '>' ];\r
+ \r
+ n = html.length;\r
+ if( ( xnodes = this._xnodes ) && ( l = xnodes.length ) ){\r
+ for( i = 0; i < l; ++i ){\r
+ html[ n ] = xnodes[ i ]._actualCreate();\r
+ ++n;\r
+ };\r
+ };\r
+ X.Dom.DTD.EMPTY[ this._tag.toLowerCase() ] || ( html[ n ] = '<\/' + this._tag + '>' );\r
+ \r
+ delete this._newAttrs;\r
+ };\r
+ delete this._dirty;\r
+ delete this._rawNode;\r
+ \r
+ return html.join( '' );\r
+ }) :\r
+ (function(){});\r
+\r
+Node.prototype._afterActualCreate =\r
+ document.getElementById ? (function(){\r
+ var xnodes, l, elm, attrs, k, i;\r
+ \r
+ this.state = Node.STATE_STAGED;\r
+ delete this._dirty;\r
+ if( this._xnodeType === 3 ){\r
+ //elm.UID = this._uid;\r
+ return this;\r
+ };\r
+ delete this._newAttrs;\r
+ \r
+ xnodes = this._xnodes;\r
+ l = xnodes && xnodes.length;\r
+ elm = this._rawNode;\r
+ \r
+ if( this._isNew ){\r
+ if( !Node._useDocumentFragment && l ){// docFrg が使えない場合、doc 追加後に子を追加\r
+ for( i = 0; i < l; ++i ){\r
+ elm.appendChild( xnodes[ i ]._actualCreate( true ) );\r
+ };\r
+ };\r
+ if( !X.UA.IE ){\r
+ elm.UID = this._uid;\r
+ if( this._id ) elm.id = this._id;\r
+ if( this._className ) elm.className = this._className;\r
+ if( attrs = this._attrs ){\r
+ for( k in attrs ){\r
+ elm[ k ] = attrs[ k ];\r
+ };\r
+ };\r
+ elm.style.cssText = this._cssText;\r
+ };\r
+ this._restoreEvent();// イベントの復帰\r
+ delete this._isNew;\r
+ };\r
+ if( l ){\r
+ for( i = 0; i < l; ++i ){\r
+ xnodes[ i ]._afterActualCreate();\r
+ };\r
+ };\r
+ return this;\r
+ }) :\r
+ document.all ? (function(){\r
+ var xnodes, i;\r
+ this.state = Node.STATE_STAGED;\r
+ \r
+ if( this._xnodeType !== 1 ) return this;\r
+ \r
+ if( ( xnodes = this._xnodes ) && ( i = xnodes.length ) ){\r
+ for( ; i; ){\r
+ xnodes[ --i ]._afterActualCreate();\r
+ };\r
+ };\r
+ return this._restoreEvent();// イベントの復帰\r
+ }) :\r
+ (function(){});\r
+ \r
+Node.prototype._actualRemove =\r
+ document.getElementById ?\r
+ ( function( isChild ){\r
+ var xnodes = this._xnodes,\r
+ elm = this._rawNode,\r
+ child, i, l;\r
+ if( xnodes && ( l = xnodes.length ) ){\r
+ for( i = 0; i < l; ++i ){\r
+ child = xnodes[ i ];\r
+ child._xnodeType === 1 && child._actualRemove( true );\r
+ };\r
+ };\r
+ if( !elm ) return;\r
+ this._xnodeType === 1 && this._migrateEvent();// イベントの退避\r
+ // elm.parentNode.tagName check tagName is for ie7\r
+ !isChild && elm.parentNode && elm.parentNode.tagName && elm.parentNode.removeChild( elm );\r
+ }) :\r
+ document.all ? \r
+ ( function( isChild ){\r
+ var xnodes = this._xnodes,\r
+ elm = this._rawNode || this._ie4getRawNode(),\r
+ i, l, xnode;\r
+ if( xnodes && ( l = xnodes.length ) ){\r
+ for( i = 0; i < l; ++i ){\r
+ xnodes[ i ]._actualRemove( true );\r
+ };\r
+ };\r
+ if( !elm ) return;\r
+ this._xnodeType === 1 && this._migrateEvent();// イベントの退避\r
+ delete this._rawNode;\r
+ elm.removeAttribute( 'id', '' );\r
+ document.all[ 'ie4uid' + this._uid ] = null;\r
+ if( !isChild ) elm.outerHTML = '';\r
+ }) :\r
+ (function(){});\r
+ \r
+ \r
//})( window, document );\r
\r
\r
*/
if( window.addEventListener ){
- X.Dom.Event = function( e ){
+ X.Dom.Event = function( e, xnode ){
//this._event = e;
this.type = e.type;
//http://www.quirksmode.org/js/events_properties.html
- this.target = e.target.nodeType === 3 ? e.target.parentNode : e.target;// defeat Safari bug // xnode
+ this.target = Node._getXNode( e.target.nodeType === 3 ? e.target.parentNode : e.target );// defeat Safari bug // xnode
- this.currentTarget = e.currentTarget; // xnode
- this.relatedTarget = e.relatedTarget; // xnode
+ this.currentTarget = xnode; // xnode
+ this.relatedTarget = Node._getXNode( e.relatedTarget ); // xnode
this.eventPhase = e.eventPhase;
this.clientX = e.clientX;
this.touches = e.touches;
this.changedTouches = e.changedTouches;
this.targetTouches = e.targetTouches;
- //this.altKey = e.altKey;
- //this.ctrlKey = e.ctrlKey;
this.metaKey = e.metaKey;
- //this.shiftKey = e.shiftKey;
- //this.type = e.type;
- //this.target = e.target;
} else
if( e.constructor === window.PointerEvent ){
// PointerEvent;
};
};
} else {
- X.Dom.Event = function( e, element ){
+ X.Dom.Event = function( e, xnode, element ){
var btn;
//this._event = e;
this.type = e.type;
- this.target = e.srcElement; // xnode
- this.currentTarget = element; // xnode
- this.relatedTarget = e.formElement ? e.formElement : e.toElement; // xnode
+ this.target = Node._getXNode( e.srcElement ); // xnode
+ this.currentTarget = xnode; // xnode
+ this.relatedTarget = Node._getXNode( e.formElement ? e.formElement : e.toElement ); // xnode
this.eventPhase = e.srcElement === element ? 2: 3;
this.clientX = e.clientX;
X.Dom.Node.prototype.handleEvent =
document.removeEventListener ?
(function( e ){
- var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( e ) );
+ var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( e, this ) );
if( ret & X.Callback.STOP_PROPAGATION ){
e.stopPropagation();
};
}) :
(function(){
- var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( event, this._rawNode ) );
+ var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( event, this, this._rawNode ) );
if( ret & X.Callback.STOP_PROPAGATION ){
event.cancelBubble = true;
*/
X.Dom.listenOnce( X.Dom.Event.DOM_INIT, function(){
- Node._html = document.documentElement ? new Node( document.documentElement ) : null;
- //alert( document.all.tags('html')[ 0 ].tagName );
+ Node._html = document.documentElement ?
+ new Node( document.documentElement ) :
+ document.getElementsByTagName ?
+ new Node( document.getElementsByTagName( 'html' )[ 0 ] ) :
+ document.all ?
+ new Node( document.all.tags( 'html' )[ 0 ] ) :
+ null;
+
var r = Node.root = new Node( document.body ),
body = r._rawNode,
- createTree, n = 0, s;
+ createTree, n = 0, xnodes, s;
r.appendTo = r.appendToRoot = r.before = r.after = r.clone = r.remove = r.destroy = r.prevNode = r.nextNode = new Function( 'return this' );
- if( body.childNodes ){
- /*
- * body.innerHTML(可能なら outerHTML を使って属性を控える)
- */
- createTree = function( xnode, elm, skipCleanup ){
- var children = elm.childNodes,
- i = 0,
- l = children.length,
- child, _xnode, text;
- for( ; i < children.length; ){
- child = children[ i ];
- switch( child.nodeType ){
- case 1 :
- if( !xnode._xnodes ) xnode._xnodes = [];
- xnode._xnodes[ xnode._xnodes.length ] = _xnode = new Node( child );
- // attr の取得
+ createTree =
+ body.childNodes ?
+ (function( xnode, childNodes, skipCleanup ){
+ var i = 0,
+ l,
+ j = 0,
+ child, _xnode, f, tag, text, _xtext, ary = [];
+ //Array.prototype.push.apply( ary, childNodes );
+ ary = X.copyArray( childNodes );
+ childNodes = ary;
+ l = childNodes.length;
+ //xnode._dirtychildNodes = true;
+ for( ; i < l; ++i ){
+ child = childNodes[ i ];
+ if( ( child.nodeType !== 1 && child.nodeType !== 3 ) || child.tagName === '!' ){
+ child.parentNode.removeChild( child );
+ continue;
+ };
+ //if( child.tagName === '!' ) continue;
+ f = false;
+ while( xnode._xnodes && j < xnode._xnodes.length ){
+ _xnode = xnode._xnodes[ j ];
_xnode.parent = xnode;
- child.childNodes.length && createTree( _xnode, child, skipCleanup || 0 <= X.Dom.skipCleanupTagNames.indexOf( child.tagName ) );//.toLowerCase() ) );
- break;
- case 3 :
- if( skipCleanup || ( ( text = child.data ) && ( text = X.Dom.cleanupWhiteSpace( text ) ) !== ' ' ) ){
- if( !skipCleanup ) child.data = text;
- if( !xnode._xnodes ) xnode._xnodes = [];
- xnode._xnodes[ xnode._xnodes.length ] = _xnode = new Node( child );
- _xnode.parent = xnode;
- break;
- };
- default :
- elm.removeChild( child );
- ++n;
- continue;
- };
- ++i;
- };
- };
- createTree( r, body );
- } else
- if( body.children ){
- createTree = function( xnode, children, skipCleanup ){
- var i = 0,
- l = children.length,
- j = 0,
- child, _xnode, f, tag, text;
- xnode._ie4dirtyChildren = true;
- for( ; i < l; ++i ){
- child = children[ i ];
- if( child.tagName === '!' ) continue;
- f = false;
- while( j < xnode._xnodes.length ){
- _xnode = xnode._xnodes[ j ];
- _xnode.parent = xnode;
- _xnode._ie4dirty = true;
- if( _xnode._xnodeType === 1 ){
- tag = child.tagName; //.toLowerCase();
- if( _xnode._tag !== tag ){
- alert( _xnode._tag + ' !== ' + child.tagName + ' * ' + child.outerHTML );
- } else {
+ if( _xnode._xnodeType === 1 ){
+ _xtext = null;
+ if( child.nodeType !== 1 ){
+ if( !( text = child.data ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' || !text ){
+ child.parentNode.removeChild( child );
+ break;
+ };
+ alert( '[' +xnode._tag + '>' +_xnode._tag + '] !== ' + child.nodeType + '\n' + child.data );
+ ++j;
+ continue;
+ };
+ tag = child.tagName;
+ if( _xnode._tag.toUpperCase() !== tag ){
+ alert( '[' +xnode._tag + '>' +_xnode._tag + ' ' + (_xnode._xnodes ? _xnode._xnodes.length : '' ) + '] !== ' + child.tagName + ' ' + (child.childNodes ? child.childNodes.length : '' ) + '\n' + child.outerHTML );
+ ++j;
+ continue;
+ } else {
+ _xnode._rawNode = child;
+ child.UID = _xnode._uid;
+ if( 0 <= X.Dom.cleanupTagNames.indexOf( tag.toLowerCase() ) ){
+ //alert( '[' +xnode._tag + '>' + _xnode._tag + '] remove ... ' );
+ _xnode.destroy();
+ ++n;
+ continue;
+ } else {
+ //alert( '[' +xnode._tag + '>' + _xnode._tag + ' ' + (_xnode._xnodes ? _xnode._xnodes.length : '' ) + '] === ' + child.tagName + ' ' + (child.childNodes ? child.childNodes.length : '' ) + ' Hit\n' + child.outerHTML );
+ child.childNodes.length && createTree( _xnode, child.childNodes, skipCleanup || 0 <= X.Dom.skipCleanupTagNames.indexOf( tag.toLowerCase() ) );
+ };
+ f = true;
+ ++j;
+ break;
+ };
+ } else
+ if( _xnode._xnodeType === 3 ){
+ if( child.nodeType !== 3 ){
+ if( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
+ console.log( '[' +xnode._tag + '>' + _xnode._uid + '] destroy ... ' );
+ _xnode.destroy();
+ ++n;
+ continue;
+ };
+ alert( xnode._tag + '>' + '"' + _xnode._text + '" !== ' + child.tagName + '\n' + child.outerHTML );
+ ++j;
+ continue;
+ };
+
_xnode._rawNode = child;
- //!( _xnode._id = child.getAttribute( 'id' ) ) && child.setAttribute( 'id', ( _xnode._ie4uid = 'ie4uid' + _xnode._uid ) );
- !_xnode._id && child.setAttribute( 'id', ( _xnode._ie4uid = 'ie4uid' + _xnode._uid ) );
- child.setAttribute( 'UID', '' + _xnode._uid );
- child.children.length && createTree( _xnode, child.children, skipCleanup || 0 <= X.Dom.skipCleanupTagNames.indexOf( tag ) );
- f = true;
+
+ if( !skipCleanup ){
+ if( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
+ console.log( '[' +xnode._tag + '>' + _xnode._uid + '] destroy ... ' );
+ _xnode.destroy();
+ ++n;
+ continue;
+ };
+ if( _xtext ){
+ _xtext.text( _xtext._text + text );
+ console.log( '[' +xnode._tag + '>' + _xnode._uid + '] xtext,destroy ... ' );
+ _xnode.destroy();
+ ++n;
+ continue;
+ } else {
+ //alert( xnode._tag + '>' + '"' + text + '"\n' + child.data );
+ _xnode.text( text );
+ };
+ } else
+ if( _xtext ){
+ _xtext.text( _xtext._text + _xnode.text );
+ console.log( '[' +xnode._tag + '>' + _xnode._uid + '] xtext,destroy ... ' );
+ _xnode.destroy();
+ ++n;
+ continue;
+ };
+ _xtext = _xtext || _xnode;
++j;
break;
+ } else {
+ alert( 'no hit!' )
};
- } else
+ ++j;
+
+ };
+ //if( !f ) alert( '**** ' + child.outerHTML );
+ };
+ while( xnode._xnodes && j < xnode._xnodes.length ){
+ _xnode = xnode._xnodes[ j ];
+ _xnode.parent = xnode;
if( _xnode._xnodeType === 3 ){
- if( !skipCleanup && ( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ) ){
- _xnode.remove();
+ if( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
+ console.log( '[' +xnode._tag + '>' + _xnode._uid + '] destroy ... ' );
+ _xnode.destroy();
++n;
continue;
};
- if( !skipCleanup ) _xnode._text = text;
};
++j;
};
- if( !f ) alert( '**** ' + child.outerHTML );
- };
- };
-
- r._xnodes = [];
- Node.skipCreate = true;
- /*
- * http://support.microsoft.com/kb/812417/ja
- * PRB: outerHTML の HTML 要素のプロパティは、既定の属性は表示されません。
- *
- * body.innerHTML でなく、 body.outerHTML
- */
- r._xnodes.push.apply( r._xnodes, X.Dom.parse( body.innerHTML, true ) );
- delete Node.skipCreate;
- createTree( r, body.children );
- //alert(n + ' ' + body.innerHTML);
- r._ie4reserveUpdate();
- //alert(n + ' ' + body.innerHTML);
- r._ie4startUpdate();
- alert(n + ' ' + body.innerHTML);
- } else {
-
- };
+ }) :
+ body.children ?
+ (function( xnode, children, skipCleanup ){
+ var i = 0,
+ l = children.length,
+ j = 0,
+ flag = 0,
+ child, _xnode, tag, text;
+
+ xnode._dirtyChildren = true;
+ for( ; i < l; ++i ){
+ child = children[ i ];
+ if( child.tagName === '!' ) continue;
+ while( j < xnode._xnodes.length ){
+ _xnode = xnode._xnodes[ j ];
+ _xnode.parent = xnode;
+
+ if( _xnode._xnodeType === 1 ){
+ tag = child.tagName;
+ if( _xnode._tag !== tag ){
+ alert( _xnode._tag + ' !== ' + child.tagName + ' * ' + child.outerHTML );
+ } else {
+ _xnode._rawNode = child;
+ !_xnode._id && child.setAttribute( 'id', ( _xnode._ie4uid = 'ie4uid' + _xnode._uid ) );
+ child.setAttribute( 'UID', '' + _xnode._uid );
+ if( 0 <= X.Dom.cleanupTagNames.indexOf( tag.toLowerCase() ) ){
+ _xnode.destroy();
+ ++n;
+ continue;
+ } else {
+ child.children.length && createTree( _xnode, child.children, skipCleanup || 0 <= X.Dom.skipCleanupTagNames.indexOf( tag.toLowerCase() ) );
+ tag === 'INPUT' && ( !_xnode._attrs || !_xnode._attrs.type ) && ( _xnode._attrs.type = 'text' );
+ };
+ flag |= 3;
+ ++j;
+ break;
+ };
+ } else
+ if( _xnode._xnodeType === 3 ){
+ flag |= 4;
+ if( !skipCleanup ){
+ if( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ){
+ _xnode.destroy();
+ ++n;
+ continue;
+ };
+ _xnode.text( text );
+ };
+ };
+ ++j;
+ };
+ if( !( flag & 1 ) ) alert( '**** ' + child.outerHTML );
+ flag &= 6;
+ };
+ // textNode がある
+ ( flag & 4 ) && ( xnode._dirty |= X.Dom.Dirty.IE4_TEXTNODE_FIX );
+ }) :
+ (function(){});
+
+ r._xnodes = xnodes = [];
+ // body の属性値の取得
+
+ Node.skipCreate = true;
+ /*
+ * http://support.microsoft.com/kb/812417/ja
+ * PRB: outerHTML の HTML 要素のプロパティは、既定の属性は表示されません。
+ *
+ * body.innerHTML でなく、 body.outerHTML
+ */
+ xnodes.push.apply( xnodes, X.Dom.parse( body.innerHTML, true ) );
+ delete Node.skipCreate;
+
+ //alert(n + ' ' + body.innerHTML);
+
+ createTree( r, body.children );
//r.width = new Function( 'return X.Dom.getSize()[ 0 ]' );
//r.height = new Function( 'return X.Dom.getSize()[ 1 ]' );
+ i = xnodes.length;
+ Node._systemNode = s = r.create( 'div' ).className( 'hidden-sysyem-node' );
+ //alert( i + ' -> ' + xnodes.length );
+
+ r._startUpdate();
+
+ xnodes.splice( xnodes.indexOf( s ), 1 ); // hide from api user
- Node._systemNode = r.create( 'div' ).className( 'hidden-sysyem-node' );
- r._xnodes.splice( r._xnodes.indexOf( Node._systemNode ), 1 ); // hide from api user
+ //alert(n + ' ' + body.innerHTML);
} );