var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](
'X.Node',
X_Class.POOL_OBJECT,
-
{
/**
* 要素に振られるユニークID
* TODO Node の継承ができない!
*/
'Constructor' : function( v ){
+ // TODO uid = X_Node_CHASHE.indexOf( null ), uid === -1 ? X_Node_CHASHE.length : uid;
var uid = X_Node_CHASHE.length,
css, xnodes, xnode, parent;
case X_NodeType_RAW_TEXT :
if( v[ 'UID' ] ) return X_Node_CHASHE[ v[ 'UID' ] ];
for( chashe = X_Node_CHASHE, i = chashe.length; i; ){
- if( ( xnode = X_Node_CHASHE[ --i ] ) && ( xnode[ '_rawObject' ] === v ) ) return xnode;
+ if( ( xnode = chashe[ --i ] ) && ( xnode[ '_rawObject' ] === v ) ) return xnode;
};
};
};
};
-
+// TODO document.all[ uid ] -> document[ uid ]
var X_Node__ie4getRawNode = X_UA_DOM.IE4 && function ( that ){
return that[ '_rawObject' ] ||
- ( that[ '_rawObject' ] = document.all[ 'ie4uid' + that[ '_uid' ] ] ) ||
- ( that[ '_id' ] && ( that[ '_rawObject' ] = document.all[ that[ '_id' ] ] ) );
+ ( that[ '_rawObject' ] = document.all[ 'ie4uid' + that[ '_uid' ] ] || that[ '_id' ] && document.all[ that[ '_id' ] ] );
};
// 親の xnodes から v を消す
v.parent && v[ 'remove' ]();
// IE4 でテキストノードの追加、FIXED 済でない場合、親に要素の追加を通知
- if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( this[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) this[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
+ if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( ( this[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ) this[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
break;
default :
return this;
v[ 'remove' ]();
};
// IE4 でテキストノードの追加、FIXED 済でない場合、親に要素の追加を通知
- if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( this[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) this[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
+ if( X_UA[ 'IE4' ] && !v[ '_tag' ] && ( ( this[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ) this[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
break;
default :
return this;
};
/**
- * 要素を抜く。
+ * 要素を親要素から抜く。jQuery の remove と異なり、インスタンスは破壊(kill)されず、再び別の親に挿入等できる
* @alias Node.prototype.remove
* @return {Node} 自身。チェインメソッド
* @example node.remove();
+ * parent.append( node ); 新しい親に追加できる
*/
function X_Node_remove(){
var parent = this.parent,
this[ '_xnodes' ] && X_Node_toggleInTreeFlag( this[ '_xnodes' ], false );
if( X_UA_DOM.IE4 ){
- elm = this[ '_rawObject' ] || X_Node__ie4getRawNode( this );
- if( elm ){
+ if( elm = this[ '_rawObject' ] || X_Node__ie4getRawNode( this ) ){
X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = this;
X_Node_reserveUpdate();
} else
- if( !this[ '_tag' ] && ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ){
+ if( !this[ '_tag' ] && ( ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ){
parent[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
};
} else {
X_Node_reserveUpdate();
};
};
+ } else {
+ if( !X_UA_DOM.IE4 ){
+ elm = this[ '_rawObject' ];
+ if( elm && elm.parentNode && elm.parentNode.tagName ){
+ X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = this;
+ X_Node_reserveUpdate();
+ };
+ };
};
return this;
};
*/
function X_Node_empty(){
var xnodes = this[ '_xnodes' ], i;
+
if( xnodes && ( i = xnodes.length ) ){
+ delete this[ '_xnodes' ];
for( ; i; ){
xnodes[ --i ][ 'kill' ]();
};
if( ( that[ '_flags' ] & X_NodeFlags_EXIST ) === 0 ) return;
- parent && parent[ '_xnodes' ].splice( parent[ '_xnodes' ].indexOf( that ), 1 );
+ parent && parent[ '_xnodes' ] && parent[ '_xnodes' ].splice( parent[ '_xnodes' ].indexOf( that ), 1 );
elm = that[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( that );
- // elm && that[ '_listeners' ] && X_EventDispatcher_unlistenAll( that ); // イベントの退避
if( xnodes && ( i = xnodes.length ) ){
+ delete that[ '_xnodes' ];
for( ; i; ){
xnodes[ --i ][ 'kill' ]();
};
+ xnodes.length = 0;
};
- delete X_Node_CHASHE[ that[ '_uid' ] ];
+ X_Node_CHASHE[ that[ '_uid' ] ] = null; // array に対して delete X_Node_CHASHE[ uid ] はまずい!
+
// remove _xnodes
if( X_UA_DOM.IE4 ){
if( elm ){
X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = elm;
X_Node_reserveUpdate();
} else
- if( !that[ '_tag' ] && ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ){
+ if( !that[ '_tag' ] && ( ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ){
parent[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN;
};
} else {
if( elm && elm.parentNode && elm.parentNode.tagName ){
X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = elm;
- X_Node_reserveUpdate();
+ X_Node_reserveUpdate();
};
};
};
// setter
if( html !== undefined ){ // String 以外に Number や false null なども許可
if( !this[ '_tag' ] ) return this[ 'text' ]( html );
- return html ? this[ 'empty' ]()[ 'append' ].apply( this, X_HtmlParser_parse( html, true ) ) : this[ 'empty' ]();
+
+ this[ 'empty' ]();
+ if( html ){
+ X_Node_append.apply( this, X_HtmlParser_parse( html, true ) );
+ };
+ return this;
};
// getter
* @example node.call( 'focus' );
*/
function X_Node_call( name /*, opt_args... */ ){
- var l = arguments.length - 1,
- v, raw, func, args, params, i;
+ var args = arguments,
+ l = args.length - 1,
+ v, raw, parent, body,
+ childX, childY, childW, childH,
+ parentW, parentH,
+ parentSX, parentSY, parentSW, parentSH,
+ visibleX, visibleY, visibleW, visibleH,
+ visiblePartX, visiblePartY, func, args, params, i;
switch( name ){
+ case 'isSVG' :
+ return !!( this[ '_flags' ] & X_NodeFlags_IS_SVG );
+ case 'isVML' :
+ return !!( this[ '_flags' ] & X_NodeFlags_IS_VML );
case 'nodeType' :
return this[ '_tag' ] ? 1 : 3;
case 'outerHTML' :
X_Node_updateTimerID && X_Node_startUpdate();
raw = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this );
+
if( !raw ) return;
if( name === 'scrollTo' ){
- raw.scrollLeft = arguments[ 1 ] || 0;
- raw.scrollTop = arguments[ 2 ] || 0;
+ raw.scrollLeft = args[ 1 ] || 0;
+ raw.scrollTop = args[ 2 ] || 0;
return;
};
+ if( name === 'inView' ){
+ body = X_elmBody;
+ child = raw;
+ visibleX = visibleY = visibleW = visibleH = 0;
+ while( child !== body ){
+ parent = child.parentNode || child.parentElement;
+ parentH = parent.clientHeight;
+ parentW = parent.clientWidth;
+ parentSW = parent.scrollHeight;
+ parentSH = parent.scrollWidth;
+ // 親がスクロール領域を持つ
+ if( parentH < parentSH || parentW < parentSW ){
+ childX = child.offsetLeft + visibleX;
+ childY = child.offsetTop + visibleY;
+ childW = visibleW || child.offsetWidth;
+ childH = visibleH || child.offsetHeight;
+ parentSX = parent.scrollLeft;
+ parentSY = parent.scrollTop;
+ // 子が表示領域内
+ if( parentSY < childY + childH &&
+ childY < parentSY + parentH &&
+ parentSX < childX + childW &&
+ childX < parentSX + parentW ){
+
+ // right:子の左側が見えている left:子の左側が見えている both:完全に見えている
+ visiblePartX =
+ childX < parentSX ? 'right' :
+ ( parentSX + parentW ) < ( childX + childW ) ? 'left' : 'both';
+ visiblePartY =
+ childY < parentSY ? 'bottom' :
+ ( parentSY + parentH ) < ( childY + childH ) ? 'top' : 'both';
+
+ // 子が見える領域
+ visibleX = visiblePartX === 'right' ? 0 : childX - parentSX;
+ visibleY = visiblePartX === 'bottom' ? 0 : childY - parentSY;
+ visibleW =
+ visiblePartX === 'both' ? childW :
+ visiblePartX === 'right' ? ( parentSX + parentW - childX ) : ( childX + childW - parentSX );
+ visibleH =
+ visiblePartY === 'both' ? childH :
+ visiblePartY === 'bottom' ? ( parentSY + parentH - childY ) : ( childY + childH - parentSY );
+ } else {
+ return { 'isInView' : false };
+ };
+ };
+ child = parent;
+ };
+ return { 'isInView' : true };
+ };
+
func = raw[ name ];
if( X_Type_isFunction( func ) ){
if( l ){
- args = X_Array_copy( arguments );
+ args = X_Array_copy( args );
args.shift();
return func.apply( raw, args );
};
return raw[ name ]();
} else
- if( X_Type_isUnknown( func ) || ( X_UA[ 'IE' ] < 9 && X_Type_isObject( func ) ) ){
+ if( X_UA[ 'IE' ] < 9 && ( X_Type_isUnknown( func ) || X_Type_isObject( func ) ) ){
// typeof func === unknown に対策
// http://la.ma.la/blog/diary_200509031529.htm
if( l ){
- args = X_Array_copy( arguments );
+ args = X_Array_copy( args );
args.shift();
params = [];
// 1. GPU 一切の更新をスキップ
if( that[ '_flags' ] & X_NodeFlags_GPU_NOW ){
- console.log( '更新のskip ' + !!( that[ '_flags' ] & X_Node_BitMask_IS_DIRTY ) );
+ //console.log( '更新のskip ' + !!( that[ '_flags' ] & X_Node_BitMask_IS_DIRTY ) );
that[ '_flags' ] & X_Node_BitMask_IS_DIRTY && X_Node__updateRawNode( that, elm );
return elm;
};
accumulatedFlags |= that[ '_flags' ];
if( that[ '_flags' ] & X_NodeFlags_IE5_DISPLAY_NONE_FIX ){
- if( accumulatedFlags & ( X_NodeFlags_DIRTY_POSITION | X_NodeFlags_DIRTY_ID | X_NodeFlags_DIRTY_CLASSNAME ) === 0 ){
+ if( ( accumulatedFlags & ( X_NodeFlags_DIRTY_POSITION | X_NodeFlags_DIRTY_ID | X_NodeFlags_DIRTY_CLASSNAME ) ) === 0 ){
return nextElement;
};
};
if( !elm ){
if( !that[ '_tag' ] ){
that[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
- that[ '_rawObject' ] = elm = document.createTextNode( X_String_chrReferanceTo( that[ '_text' ] ) );
+ elm = document.createTextNode( X_String_chrReferanceTo( that[ '_text' ] ) );
if( !X_UA[ 'IE' ] ){
elm[ 'UID' ] = that[ '_uid' ];
};
if( X_Node_strictElmCreation ){
that[ '_flags' ] & X_NodeFlags_OLD_CSSTEXT && X_Node_CSS_objToCssText( that, true ); // OLD_CSSTEXT ??
- that[ '_rawObject' ] = elm =
+ elm =
document.createElement( [
'<', that[ '_tag' ],
' UID="', that[ '_uid' ], '"',
X_Node_Attr_objToAttrText( that, true ),
that[ '_cssText' ] ? ' style="' + that[ '_cssText' ] + '"' : '',
'>' ].join( '' ) );
+ } else
+ if( that[ '_flags' ] & X_NodeFlags_IS_SVG ){
+ elm = document.createElementNS( 'http://www.w3.org/2000/svg', that[ '_tag' ].toLowerCase() );
+
+ // math http://www.w3.org/1998/Math/MathML
} else {
- if( that[ '_flags' ] & X_NodeFlags_IS_SVG ){
- that[ '_rawObject' ] = elm = document.createElementNS( 'http://www.w3.org/2000/svg', that[ '_tag' ] );
- } else {
- that[ '_rawObject' ] = elm = document.createElement( that[ '_tag' ] );
- };
+ elm = document.createElement( that[ '_tag' ] );
};
+ that[ '_rawObject' ] = elm;
+
// IE には要素追加のタイミングで起こるメモリリークがありここで追加
if( !X_Node_addTreeAfterChildren ){
nextElement ?
X_EventDispatcher_toggleAllEvents( that, true );// イベントの復帰
that[ '_flags' ] |= X_NodeFlags_ACTUAL_LISTENING;
- if( X_Node_documentFragment ){
+ //if( X_Node_documentFragment ){
//( frg = X_Node_documentFragment ).appendChild( elm );
// 連続する要素の差し替えの場合に有効
- };
+ //};
if( X_Node_strictElmCreation ){
that[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY;
parentElement.appendChild( elm );
};
- if( that[ '_listeners' ] && ( that[ '_flags' ] & X_NodeFlags_ACTUAL_LISTENING ) === 0 ){
+ if( that[ '_listeners' ] && ( ( that[ '_flags' ] & X_NodeFlags_ACTUAL_LISTENING ) === 0 ) ){
X_EventDispatcher_toggleAllEvents( that, true );// イベントの退避
that[ '_flags' ] |= X_NodeFlags_ACTUAL_LISTENING;
};
};
// id
if( that[ '_flags' ] & X_NodeFlags_DIRTY_ID ){
- that[ '_id' ] ? ( elm.id = that[ '_id' ] ) : ( elm.id && elm.removeAttribute( 'id' ) );
+ that[ '_id' ] ?
+ ( ( that[ '_flags' ] & X_NodeFlags_IS_SVG ) ?
+ elm.setAttribute( 'id', that[ '_id' ] ) :
+ ( elm.id = that[ '_id' ] )
+ ) :
+ ( elm.id && elm.removeAttribute( 'id' ) );
};
// className
if( that[ '_flags' ] & X_NodeFlags_DIRTY_CLASSNAME ){
- that[ '_className' ] ? ( elm.className = that[ '_className' ] ) : ( elm.className && elm.removeAttribute( X_UA[ 'IE' ] < 8 ? 'className' : 'class' ) ); // className は ie7-
+ that[ '_className' ] ?
+ ( ( that[ '_flags' ] & X_NodeFlags_IS_SVG ) ?
+ elm.setAttribute( 'class', that[ '_className' ] ) :
+ ( elm.className = that[ '_className' ] )
+ ) :
+ ( elm.className && elm.removeAttribute( X_UA[ 'IE' ] < 8 ? 'className' : 'class' ) ); // className は ie7-
};
// attr
// TODO IE では input, なぜか button, object も type, name の変更が出来ない、同値で置き換えようとしても不可
v === undefined ?
elm.removeAttribute( rename[ k ] || k ) :
- ( elm[ rename[ k ] || k ] = X_Node_Attr_noValue[ k ] ? k : v );
+ ( ( that[ '_flags' ] & X_NodeFlags_IS_SVG ) ?
+ elm.setAttribute( k, v ) :
+ ( elm[ rename[ k ] || k ] = X_Node_Attr_noValue[ k ] ? k : v )
+ );
};
delete that[ '_newAttrs' ];
};