var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](
'X.Node',
X_Class.POOL_OBJECT,
-
{
/**
* 要素に振られるユニークID
*/
function X_Node_clone( opt_clone_children ){
var xnode, xnodes, i, l;
+
if( this[ '_tag' ] ){
X_Node_newByTag = true;
xnode = Node( this[ '_tag' ], X_Object_copy( this[ '_attrs' ] ), X_Object_copy( this[ '_css' ] ) )
[ 'attr' ]( { 'id' : this[ '_id' ] } )
[ 'className' ]( this[ '_className' ] );
+
+ if( this[ '_flags' ] & X_NodeFlags_IS_SVG ){
+ xnode[ '_flags' ] |= X_NodeFlags_IS_SVG;
+ };
+ if( this[ '_flags' ] & X_NodeFlags_IS_VML ){
+ xnode[ '_flags' ] |= X_NodeFlags_IS_VML;
+ };
+
if( opt_clone_children && ( xnodes = this[ '_xnodes' ] ) && ( l = xnodes.length ) ){
for( i = 0; i < l; ++i ){
xnode[ 'append' ]( xnodes[ i ][ 'clone' ]( true ) );
};
};
- return xnode;
+ return xnode;
};
X_Node_newByText = true;
return Node( this[ '_text' ] );
// 親の 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[ '_xnodes' ] && X_Node_toggleInTreeFlag( v[ '_xnodes' ], true );
X_Node_reserveUpdate();
};
+ if( this[ '_flags' ] & X_NodeFlags_IS_SVG ){
+ v[ '_flags' ] |= X_NodeFlags_IS_SVG;
+ };
+ if( this[ '_flags' ] & X_NodeFlags_IS_VML ){
+ v[ '_flags' ] |= X_NodeFlags_IS_VML;
+ };
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;
v[ '_xnodes' ] && X_Node_toggleInTreeFlag( v[ '_xnodes' ], true );
X_Node_reserveUpdate();
};
+ if( this[ '_flags' ] & X_NodeFlags_IS_SVG ){
+ v[ '_flags' ] |= X_NodeFlags_IS_SVG;
+ };
+ if( this[ '_flags' ] & X_NodeFlags_IS_VML ){
+ v[ '_flags' ] |= X_NodeFlags_IS_VML;
+ };
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
return this[ '_text' ];
};
-/*
+/**
* HTML要素に対して name の関数を実行しその戻り値を返す。関数に渡す引数も任意に設定できる。
+ * @alias Node.prototype.call
+ * @param {string} [name] 要素の関数名
+ * @return {*}
+ * @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 = [];
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 {
- 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' ];
};