From 50462b7b22a3c42bdbf2fb84d782937f817368f4 Mon Sep 17 00:00:00 2001 From: itozyun Date: Fri, 10 Apr 2015 12:02:29 +0900 Subject: [PATCH] Version 0.6.137, fix X.EventDispatcher.unlisten & remove X.Node.destroy. --- 0.6.x/js/01_core/11_XClass.js | 2 +- 0.6.x/js/01_core/13_XEventDispatcher.js | 49 +++--- 0.6.x/js/02_dom/00_XDoc.js | 8 +- 0.6.x/js/02_dom/02_XNode.js | 269 ++++++++++++++++++++---------- 0.6.x/js/02_dom/07_XNodeList.js | 2 - 0.6.x/js/02_dom/08_XNodeSelector.js | 72 ++++++-- 0.6.x/js/02_dom/22_XTreeBuilder.js | 16 +- 0.6.x/js/05_util/01_XNinjaIframe.js | 111 ++++++------ 0.6.x/js/05_util/03_XUtilImage.js | 2 +- 0.6.x/js/06_net/02_XNetJSONP.js | 2 +- 0.6.x/js/06_net/04_XNetImage.js | 2 +- 0.6.x/js/07_audio/00_XAudio.js | 22 +-- 0.6.x/js/07_audio/03_XSilverlightAudio.js | 2 +- 0.6.x/js/07_audio/10_XAudioSprite.js | 16 +- 0.6.x/js/20_ui/06_AbstractUINode.js | 2 +- 0.6.x/js/20_ui/20_PageRoot.js | 8 +- 16 files changed, 359 insertions(+), 226 deletions(-) diff --git a/0.6.x/js/01_core/11_XClass.js b/0.6.x/js/01_core/11_XClass.js index 6ead421..1a5499e 100644 --- a/0.6.x/js/01_core/11_XClass.js +++ b/0.6.x/js/01_core/11_XClass.js @@ -77,7 +77,7 @@ X_Class_CommonMethods = }; this[ 'dispatch' ]( X_EVENT_KILL_INSTANCE ); - this[ '_listeners' ] && X_EventDispatcher_systemUnlisten( this ); + this[ '_listeners' ] && X_EventDispatcher_unlistenAll( this ); }; for( p in instance ){ diff --git a/0.6.x/js/01_core/13_XEventDispatcher.js b/0.6.x/js/01_core/13_XEventDispatcher.js index 121525b..946cbfc 100644 --- a/0.6.x/js/01_core/13_XEventDispatcher.js +++ b/0.6.x/js/01_core/13_XEventDispatcher.js @@ -105,7 +105,7 @@ var X_EventDispatcher_once = false, * @constructs EventDispatcher * @extends {__ClassBase__} */ -var X_EventDispatcher = X.EventDispatcher = +var X_EventDispatcher = X[ 'EventDispatcher' ] = X_Class_create( 'EventDispatcher', @@ -434,13 +434,11 @@ function X_EventDispatcher_systemListen( that, type, opt_arg1, opt_arg2, opt_arg X_EventDispatcher_lock = false; }; -// TODO this[ 'listen' ](type) は this リスナの登録なのに、this[ 'unlisten' ](type)は全てのtypeの削除、と不一致 - /** * イベントリスナの解除を行う。登録時と同じ引数を与える必要がある。kill() ですべてのイベントが解除されるので、途中で解除されるイベント以外は kill() に任せてしまってよい。 * @alias EventDispatcher.prototype.unlisten * @return {EventDispatcher} - * @param {string|number|Array.} opt_type + * @param {string|number|Array.} opt_type イベントID, イベント名、またはその配列 * @param {listener|function|Array} opt_arg1 * @param {function|Array} opt_arg2 * @param {Array} opt_arg3 @@ -459,29 +457,7 @@ function X_EventDispatcher_unlisten( opt_type, opt_arg1, opt_arg2, opt_arg3 ){ }; return this; }; - - if( opt_type === undefined ){ - // 全て削除 - for( opt_type in listeners ){ - //if( X_EMPTY_OBJECT[ opt_type ] ) continue; - if( opt_type < X_Listeners_.KILL_RESERVED ) continue; - list = listeners[ opt_type ]; - for( i = list.length; i; ){ - this[ 'unlisten' ]( opt_type, list[ --i ] ); // override されていることがあるので、必ず unlisten を使用 - }; - // this[ 'unlisten' ]( opt_type ); これは無茶! - }; - return this; - } else - if( opt_arg1 === undefined ){ - // 同一タイプを全て削除 - if( list = listeners[ opt_type ] ){ - for( i = list.length; i; ){ - this[ 'unlisten' ]( opt_type, list[ --i ] ); // override されていることがあるので、必ず unlisten を使用 - }; - }; - return this; - } else + if( reserves = listeners[ X_Listeners_.RESERVES ] ){ for( i = reserves.length; i; ){ f = reserves[ --i ]; @@ -515,7 +491,7 @@ function X_EventDispatcher_unlisten( opt_type, opt_arg1, opt_arg2, opt_arg3 ){ // TODO カウンター empty = true; for( k in listeners ){ - if( k < X_Listeners_.KILL_RESERVED ) continue; + if( k <= X_Listeners_.KILL_RESERVED ) continue; empty = false; break; }; @@ -537,6 +513,21 @@ function X_EventDispatcher_systemUnlisten( that, type, opt_arg1, opt_arg2, opt_a X_EventDispatcher_unlock = false; }; +function X_EventDispatcher_unlistenAll( that ){ + var listeners = that[ '_listeners' ], + type, list, i; + if( !listeners ) return; + + for( type in listeners ){ + //if( X_EMPTY_OBJECT[ opt_type ] ) continue; + if( type <= X_Listeners_.KILL_RESERVED ) continue; + list = listeners[ type ]; + for( i = list.length; i; ){ + that[ 'unlisten' ]( type, list[ --i ] ); + }; + }; +}; + function X_EventDispatcher_addEvent( that, type, raw, list ){ var i; X_EventDispatcher_lock || ( type = X_Event_Rename[ type ] || type ); @@ -840,7 +831,7 @@ function X_EventDispatcher_toggleAllEvents( that, add ){ if( !list || !raw ) return; for( type in list ){ //if( X_EMPTY_OBJECT[ type ] ) continue; - //if( type < X_Listeners_.KILL_RESERVED ) continue; + //if( type <= X_Listeners_.KILL_RESERVED ) continue; // 数字イベントの除外 if( !X_String_isNumberString( type ) ){ // TODO type rename はここ diff --git a/0.6.x/js/02_dom/00_XDoc.js b/0.6.x/js/02_dom/00_XDoc.js index e2fcbf8..48251a6 100644 --- a/0.6.x/js/02_dom/00_XDoc.js +++ b/0.6.x/js/02_dom/00_XDoc.js @@ -12,7 +12,7 @@ X[ 'Doc' ] = { X_ViewPort_document[ 'asyncDispatch' ]( type ); }; type && arg1 && X_ViewPort_document[ 'listen' ]( type, arg1, arg2, arg3 ); - return X.Doc; + return X[ 'Doc' ]; }, @@ -24,12 +24,12 @@ X[ 'Doc' ] = { X_ViewPort_document[ 'asyncDispatch' ]( type ); }; type && arg1 && X_ViewPort_document[ 'listenOnce' ]( type, arg1, arg2, arg3 ); - return X.Doc; + return X[ 'Doc' ]; }, 'unlisten' : function( type, arg1, arg2, arg3 ){ type && arg1 && X_ViewPort_document[ 'unlisten' ]( type, arg1, arg2, arg3 ); - return X.Doc; + return X[ 'Doc' ]; }, 'listening' : function( type, arg1, arg2, arg3 ){ @@ -63,7 +63,7 @@ function X_Doc_create( tag, opt_attrs, opt_css ){ case X_Node_TYPE.HTML_STRING : list = X_HtmlParser_parse( tag, true ); for( i = list.length; 1 < i; ){ - list[ --i ].destroy(); + list[ --i ][ 'kill' ](); }; return list[ 0 ]; }; diff --git a/0.6.x/js/02_dom/02_XNode.js b/0.6.x/js/02_dom/02_XNode.js index b3e6576..ab3d01c 100644 --- a/0.6.x/js/02_dom/02_XNode.js +++ b/0.6.x/js/02_dom/02_XNode.js @@ -109,7 +109,7 @@ var X_Node_BITMASK_RESET_STYLE = ( ( 2 << 29 ) - 1 + ( 2 << 29 ) ) ^ ( */ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ]( 'X.Node', - X_Class.POOL_OBJECT, // X_Class.FINAL + X_Class.POOL_OBJECT, { /** @@ -313,8 +313,8 @@ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ]( return X_Node_none; default : - this.length = 0; if( X_Node_none ) return X_Node_none; + this.length = 0; return; }; }; @@ -324,6 +324,8 @@ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ]( }; this[ '_flags' ] |= X_Node_State.EXIST; X_Node_CHASHE[ this[ '_uid' ] = uid ] = this; + + X_EventDispatcher_systemListen( this, X_EVENT_BEFORE_KILL_INSTANCE, X_Node_onBeforeKill ); }, // attr @@ -347,9 +349,9 @@ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ]( 'appendTo' : X_Node_appendTo, - 'prev' : X_Node_before, + 'prev' : X_Node_prev, - 'next' : X_Node_after, + 'next' : X_Node_next, 'swap' : X_Node_swap, @@ -357,13 +359,11 @@ var Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ]( 'empty' : X_Node_empty, - destroy : X_Node_destroy, // -> kill && kill event - 'contains' : X_Node_contains, 'getChildAt' : X_Node_getChildAt, - 'numChildren' : X_Node_length, + 'numChildren' : X_Node_numChildren, 'firstChild' : X_Node_firstChild, @@ -397,6 +397,7 @@ function X_Node_getType( v ){ if( X_Type_isString( v ) ){ return '<' === v.charAt( 0 ) && v.charAt( v.length - 1 ) === '>' ? X_Node_TYPE.HTML_STRING : X_Node_TYPE.STRING; }; + if( v[ 'instanceOf' ] && v[ 'instanceOf' ]( Node ) ) return X_Node_TYPE.XNODE; return 0; }; function X_Node_getXNode( v ){ @@ -437,7 +438,7 @@ var X_Node_isXmlDocument = return root.isXML = root[ '_rawObject' ].createElement( 'p' ).tagName !== root[ '_rawObject' ].createElement( 'P' ).tagName; }), X_Node_CHASHE = [], - X_Node_none = X_Node_CHASHE[ 0 ] = new Node(), + X_Node_none = X_Node_CHASHE[ 0 ] = Node(), X_Node_html, // = X_Node_CHASHE[ 1 ] X_Node_head, // = X_Node_CHASHE[ 2 ] X_Node_body, // = X_Node_CHASHE[ 3 ] @@ -562,7 +563,7 @@ function X_Node_clone( opt_clone_children ){ var xnode, xnodes, i, l; if( this[ '_tag' ] ){ X_Node_newByTag = true; - xnode = new Node( this[ '_tag' ], X_Object_clone( this[ '_attrs' ] ), X_Object_clone( this[ '_css' ] ) ) + xnode = Node( this[ '_tag' ], X_Object_clone( this[ '_attrs' ] ), X_Object_clone( this[ '_css' ] ) ) [ 'attr' ]( { 'id' : this[ '_id' ] } ) [ 'className' ]( this[ '_className' ] ); if( opt_clone_children && ( xnodes = this[ '_xnodes' ] ) && ( l = xnodes.length ) ){ @@ -573,12 +574,12 @@ function X_Node_clone( opt_clone_children ){ return xnode; }; X_Node_newByText = true; - return new Node( this[ '_text' ] ); + return Node( this[ '_text' ] ); }; /** * ノードを子配列の最後に追加する。文字列が渡された場合、HTMLパーサーによって Node ツリーを作成して追加する。HtmlElement, TextNode の場合は内部使用専用。 - * @alias Node.prototype.clone + * @alias Node.prototype.append * @param {Node|string|HTMLElement|TextNode} [v] HTMLElement と TextNode は内部のみ。 * @return {Node} 自身。チェインメソッド * @example myNode.append( node ); @@ -600,7 +601,7 @@ function X_Node_append( v ){ switch( X_Node_getType( v ) ){ case X_Node_TYPE.RAW_HTML : case X_Node_TYPE.RAW_TEXT : - v = new Node( v ); + v = Node( v ); break; case X_Node_TYPE.HTML_STRING : case X_Node_TYPE.STRING : @@ -627,7 +628,7 @@ function X_Node_append( v ){ /** * ノードを挿入位置に追加する。 - * @alias Node.prototype.clone + * @alias Node.prototype.appendAt * @param {number} index 挿入位置 0以上 * @param {Node|string|HTMLElement|TextNode} [v] HTMLElement と TextNode は内部のみ。 * @return {Node} 自身。チェインメソッド @@ -659,7 +660,7 @@ function X_Node_appendAt( start, v ){ switch( X_Node_getType( v ) ){ case X_Node_TYPE.RAW_HTML : case X_Node_TYPE.RAW_TEXT : - v = new Node( v ); + v = Node( v ); break; case X_Node_TYPE.HTML_STRING : case X_Node_TYPE.STRING : @@ -688,10 +689,18 @@ function X_Node_appendAt( start, v ){ return this; }; +/** + * ノードを親に追加する。戻り値は子ノードなので、続けて操作が出来る。 + * @alias Node.prototype.appendTo + * @param {Node|string|HTMLElement} [parent] HTMLElement は内部のみ。 + * @param {number} [opt_index=-1] 挿入位置。省略した場合は最後に追加する。 + * @return {Node} 自身。チェインメソッド + * @example childNode.appendTo( parentNode, 1 ); + */ function X_Node_appendTo( parent, opt_index ){ switch( X_Node_getType( parent ) ){ case X_Node_TYPE.RAW_HTML : - parent = new Node( parent ); + parent = Node( parent ); break; case X_Node_TYPE.HTML_STRING : parent = X_HtmlParser_parse( parent, true ); @@ -701,14 +710,19 @@ function X_Node_appendTo( parent, opt_index ){ default : return this; }; - opt_index === undefined ? parent[ 'append' ]( this ) : parent[ 'appendAt' ]( opt_index, this ); + X_Type_isFinite( opt_index ) ? parent[ 'appendAt' ]( opt_index, this ) : parent[ 'append' ]( this ); return this; }; -/* -------------------------------------- - * Before , After, Replace + +/** + * ノードの直前の要素を取得。または直前に挿入。 + * @alias Node.prototype.prev + * @param {Node|string|HTMLElement|TextNode} [v] HTMLElement と TextNode は内部のみ。 + * @return {Node} 自身。チェインメソッド + * @example childNode.prev( prevNode ); */ -function X_Node_before( v ){ +function X_Node_prev( v ){ var parent = this.parent, xnodes, i, l, start; // getter @@ -733,7 +747,14 @@ function X_Node_before( v ){ return this; }; -function X_Node_after( v ){ +/** + * ノードの直後の要素を取得。または直後に挿入。 + * @alias Node.prototype.next + * @param {Node|string|HTMLElement|TextNode} [v] HTMLElement と TextNode は内部のみ。 + * @return {Node} 自身。チェインメソッド + * @example childNode.next( prevNode ); + */ +function X_Node_next( v ){ var parent = this.parent, xnodes, i, l, start; // getter @@ -768,13 +789,23 @@ function X_Node_after( v ){ return this; }; +/** + * 要素の入れ替え。自身は remove() される。 + * @alias Node.prototype.swap + * @param {Node|string|HTMLElement|TextNode} [v] HTMLElement と TextNode は内部のみ。 + * @return {Node} 自身。チェインメソッド + * @example node.swap( newNode ); + */ function X_Node_swap( v ){ if( !this.parent ) return this; - return arguments.length === 1 ? this[ 'prev' ]( v )[ 'remove' ]() : X_Node_before.apply( this, arguments )[ 'remove' ](); + return arguments.length === 1 ? this[ 'prev' ]( v )[ 'remove' ]() : X_Node_prev.apply( this, arguments )[ 'remove' ](); }; -/* -------------------------------------- - * Remove +/** + * 要素を抜く。 + * @alias Node.prototype.remove + * @return {Node} 自身。チェインメソッド + * @example node.remove(); */ function X_Node_remove(){ var parent = this.parent, @@ -809,54 +840,30 @@ function X_Node_remove(){ return this; }; +/** + * 子要素を破棄する。子要素は kill() されます。 + * @alias Node.prototype.empty + * @return {Node} 自身。チェインメソッド + * @example node.empty(); + */ function X_Node_empty(){ var xnodes = this[ '_xnodes' ], i; if( xnodes && ( i = xnodes.length ) ){ for( ; i; ){ - xnodes[ --i ].destroy(); + xnodes[ --i ][ 'kill' ](); }; xnodes.length = 0; }; return this; }; -/* -------------------------------------- - * TODO destory -> kill - */ - -function X_Node_destroy( isChild ){ - var xnodes = this[ '_xnodes' ], i, elm; - - if( ( this[ '_flags' ] & X_Node_State.EXIST ) === 0 ) return; - - elm = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this ); - - if( xnodes && ( i = xnodes.length ) ){ - //for( ; i; ){ - // xnodes[ --i ].destroy( true ); - //}; - }; - elm && this[ '_listeners' ] && this[ 'unlisten' ](); // イベントの退避 - - if( this[ '_flags' ] & X_Node_State.IN_TREE ){ - !isChild && this[ 'remove' ](); - this[ '_flags' ] &= ~X_Node_State.EXIST; - } else { - this.parent && this.parent[ '_xnodes' ].splice( this.parent[ '_xnodes' ].indexOf( this ), 1 ); - elm && !isChild && X_Node__actualRemove( this ); - this[ 'kill' ](); - }; - - delete X_Node_CHASHE[ this[ '_uid' ] ]; -}; - function X_Node_onBeforeKill( e ){ var xnodes = this[ '_xnodes' ], i, elm; if( ( this[ '_flags' ] & X_Node_State.EXIST ) === 0 ) return X_Callback_NONE; elm = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this ); - elm && this[ '_listeners' ] && this[ 'unlisten' ](); // イベントの退避 + elm && this[ '_listeners' ] && X_EventDispatcher_unlistenAll( this ); // イベントの退避 if( xnodes && ( i = xnodes.length ) ){ for( ; i; ){ @@ -877,64 +884,100 @@ function X_Node_onBeforeKill( e ){ }; -/* -------------------------------------- - * contains +/** + * 要素を子以下に持つか?調べる。 + * @alias Node.prototype.contains + * @param {Node|string|HTMLElement|TextNode} [v] HTMLElement と TextNode は内部のみ。 + * @return {boolean} + * @example node.contains( testNode ); */ function X_Node_contains( v ){ var elm, type, xnodes, i; if( !v || !this[ '_tag' ] || this === v ) return false; // contains ie4+ if( ( elm = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this ) ) && document.contains && ( type = X_Node_getType( v ) ) && ( type === X_Node_TYPE.RAW_HTML || type === X_Node_TYPE.RAW_TEXT ) ){ - return elm[ 'contains' ]( v ); + return elm.contains( v ); }; + //if( document.compareDocumentPosition ){ // //}; xnodes = this[ '_xnodes' ]; if( !xnodes || !xnodes.length ) return false; if( xnodes.indexOf( v ) !== -1 ) return true; // fast - if( elm === v.parentNode ) return true; for( i = xnodes.length; i; ){ if( xnodes[ --i ][ 'contains' ]( v ) ) return true; }; return false; }; -/* -------------------------------------- - * getChild +/** + * index の子要素を取得する。 + * @alias Node.prototype.getChildAt + * @param {number} index 取得する子ノードの位置。0~ + * @return {Node} 子要素 + * @example child1 = parent.getChildAt(1); */ function X_Node_getChildAt( i ){ var xnodes = this[ '_xnodes' ]; return xnodes && 0 <= i && i < xnodes.length && xnodes[ i ]; }; -function X_Node_length(){ +/** + * 子要素の数を取得する。 + * @alias Node.prototype.numChildren + * @return {number} 子要素の数。 + * @example n = parent.numChildren(); + */ +function X_Node_numChildren(){ var xnodes = this[ '_xnodes' ]; return xnodes ? xnodes.length : 0; }; -/* -------------------------------------- - * firstChild, lastChild +/** + * 最初の子要素を取得する。 + * @alias Node.prototype.firstChild + * @return {Node} 最初の子要素 + * @example child0 = parent.firstChild(); */ function X_Node_firstChild(){ return this[ '_xnodes' ] && this[ '_xnodes' ][ 0 ]; }; + +/** + * 最後の子要素を取得する。 + * @alias Node.prototype.lastChild + * @return {Node} 最後の子要素 + * @example lastChild = parent.lastChild(); + */ function X_Node_lastChild(){ var xnodes = this[ '_xnodes' ]; return xnodes && xnodes[ xnodes.length - 1 ]; }; -/* -------------------------------------- - * getOrder +/** + * 要素の index 位置を取得する。 + * @alias Node.prototype.getOrder + * @return {number} index -1 の場合、親を持たない。 + * @example index = node.getOrder(); */ function X_Node_getOrder(){ var parent = this.parent; - if( !parent ) return -1; - return parent[ '_xnodes' ].indexOf( this ); + return this === X_Node_html ? + 0 : + parent ? + parent[ '_xnodes' ].indexOf( this ) : + -1; }; -/* -------------------------------------- - * className, addClass, removeClass, hasClass +/** + * className の取得と設定。 + * @alias Node.prototype.className + * @return {string|Node} getter の場合 class 文字列、setter の場合自身。 + * @example // getter + * className = node.className(); + * // setter + * node.className( 'myClass myClass_new' ); */ function X_Node_className( v ){ var node, _, __; @@ -960,9 +1003,18 @@ function X_Node_className( v ){ this[ '_flags' ] & X_Node_State.IN_TREE && X_Node_reserveUpdate(); return this; }; + +/** + * className の追加。 + * @alias Node.prototype.addClass + * @param {string} className スペース区切りで複数のクラスを追加できる。 + * @return {Node} 自身。 + * @example node.addClass( 'myClass myClass_new' ); + */ function X_Node_addClass( v ){ - var names = v.split( ' ' ), - i = names.length, + var names = v.split( ' ' ), + i = names.length, + _class = this[ '_className' ], name; v = ''; for( ; i; ){ @@ -970,18 +1022,27 @@ function X_Node_addClass( v ){ if( !name ) continue; !this[ 'hasClass' ]( name ) && ( v += ( v ? ' ' : '' ) + name ); }; - return v ? this[ 'className' ]( this[ '_className' ] + ( this[ '_className' ] ? ' ' : '' ) + v ) : this; + return v ? this[ 'className' ]( ( _class ? _class + ' ' : '' ) + v ) : this; }; + +/** + * className の削除。 + * @alias Node.prototype.removeClass + * @param {string} className スペース区切りで複数のクラスを削除できる。 + * @return {Node} 自身。 + * @example node.removeClass( 'myClass myClass_new' ); + */ function X_Node_removeClass( v ){ - var _ = ' ', - className = this[ '_className' ], - names = v.split( _ ), + var _ = ' ', + _class = this[ '_className' ], + names = v.split( _ ), classNames, i, f, j; - if( !className ) return this; - for( classNames = className.split( _ ), i = classNames.length; i; ){ - className = classNames[ --i ]; + + if( !_class ) return this; + for( classNames = _class.split( _ ), i = classNames.length; i; ){ + _class = classNames[ --i ]; for( j = names.length; j; ){ - if( className === names[ --j ] ){ + if( _class === names[ --j ] ){ classNames.splice( i, 1 ); names.splice( j, 1 ); f = true; @@ -991,10 +1052,19 @@ function X_Node_removeClass( v ){ }; return f ? this[ 'className' ]( classNames.join( _ ) ) : this; }; + +/** + * className の更新。 + * @alias Node.prototype.toggleClass + * @param {string} className スペース区切りで複数のクラスを削除できる。 + * @param {boolean} [opt_toggle=] true はクラスの追加。false はクラスの削除。undefined はクラスのトグル。 + * @return {Node} 自身。 + * @example node.toggleClass( 'myClass myClass_new', !!n ); + */ function X_Node_toggleClass( v, opt_toggle ){ var names, i, name; if( opt_toggle !== undefined ){ - return !!opt_toggle ? this[ 'addClass' ]( v ) : this[ 'removeClass' ]( v ); + return !opt_toggle ? this[ 'removeClass' ]( v ) : this[ 'addClass' ]( v ); }; names = v.split( ' ' ); for( i = names.length; i; ){ @@ -1003,28 +1073,38 @@ function X_Node_toggleClass( v, opt_toggle ){ }; return this; }; + +/** + * className を持つか。 + * @alias Node.prototype.hasClass + * @param {string} className スペース区切りで複数のクラスを削除できる。 + * @return {boolean} + * @example node.hasClass( 'myClass myClass_new' ); + */ function X_Node_hasClass( v ){ var _ = ' ', - className = this[ '_className' ], + _class = this[ '_className' ], i, name; - if( className === v ) return true; - if( !className ) return false; + if( _class === v ) return true; + if( !_class ) return false; - className = _ + className + _; - if( className.indexOf( _ + v + _ ) !== -1 ) return true; // lucky hit + _class = _ + _class + _; + if( _class.indexOf( _ + v + _ ) !== -1 ) return true; // lucky hit for( v = v.split( _ ), i = v.length; i; ){ name = v[ --i ]; if( name === '' ) continue; - if( className.indexOf( _ + name + _ ) === -1 ) return false; + if( _class.indexOf( _ + name + _ ) === -1 ) return false; }; return true; }; -/* -------------------------------------- - * html, text - * - * outerHTML が欲しい場合は、xnode.call('outerHTML') とできる。 +/** + * innerHTML 取得・設定。outerHTML が欲しい場合は、xnode.call('outerHTML') とできる。 + * @alias Node.prototype.html + * @param {string} [html=] html文字列 + * @return {string|Node} + * @example node.html( '' ); */ function X_Node_html( html ){ var _ = '', q = '"', xnodes, n, i, l; @@ -1065,6 +1145,13 @@ function X_Node_html( html ){ /* * null が来たら '', 数値等が来たら文字列化 */ +/** + * textContent 取得・設定。null が来たら '', 数値等が来たら文字列化 + * @alias Node.prototype.text + * @param {string} [text=] + * @return {string|Node} + * @example node.text( 'Hello, world!' ); + */ function X_Node_text( text ){ var xnodes, texts, i, l; // setter diff --git a/0.6.x/js/02_dom/07_XNodeList.js b/0.6.x/js/02_dom/07_XNodeList.js index b6df535..50eaff9 100644 --- a/0.6.x/js/02_dom/07_XNodeList.js +++ b/0.6.x/js/02_dom/07_XNodeList.js @@ -14,9 +14,7 @@ function X_NodeList( v ){ for( i = 0; i < l; ++i ){ xnode = args[ i ]; - //xnode = xnode && xnode.constructor === Node ? xnode : new Node( xnode ); skip = false; - //if( xnode._xnodeType === 0 ) continue; for( j = 0; j < n; ++j ){ if( this[ j ] === xnode ){ skip = true; diff --git a/0.6.x/js/02_dom/08_XNodeSelector.js b/0.6.x/js/02_dom/08_XNodeSelector.js index 578d9b2..5a0857e 100644 --- a/0.6.x/js/02_dom/08_XNodeSelector.js +++ b/0.6.x/js/02_dom/08_XNodeSelector.js @@ -396,10 +396,7 @@ function X_Node_Selector__parse( query, last ){ }; //console.log( l + ' > ' + xnodes.length + ' tag:' + tagName ); merge = {}; - for( ; i < l; ++i ){ - xnode = parents[ i ]; - xnode[ '_xnodes' ] && xnode[ '_xnodes' ].length && X_Node_Selector__fetchElements( xnodes, xnode, isAll ? '' : tagName, merge ); - }; + X_Node_Selector__fetchElements( xnodes, parents, isAll ? '' : tagName, merge ); //console.log( l + ' >> ' + xnodes.length + ' tag:' + tagName ); }; }; @@ -611,23 +608,69 @@ function X_Node_Selector__parse( query, last ){ }; }; }; - - function X_Node_Selector__fetchElements( list, parent, tag, merge ){ - var xnodes = parent[ '_xnodes' ], - l = xnodes.length, + + function X_Node_Selector__fetchElements( list, xnodes, tag, merge ){ + var l = xnodes.length, i = 0, - child, uid; + child, uid, _tag, _xnodes; for( ; i < l; ++i ){ child = xnodes[ i ]; uid = child[ '_uid' ]; - if( !merge[ uid ] && child[ '_tag' ] ){ + _tag = child[ '_tag' ]; + if( !merge[ uid ] && _tag ){ merge[ uid ] = true; - ( !tag || child[ '_tag' ] === tag ) && ( list[ list.length ] = child ); - child[ '_xnodes' ] && X_Node_Selector__fetchElements( list, child, tag, merge ); + ( !tag || tag === _tag ) && ( list[ list.length ] = child ); + if( ( _xnodes = child[ '_xnodes' ] ) && ( 1 < _xnodes.length || ( _xnodes[ 0 ] && _xnodes[ 0 ][ '_tag' ] ) ) ){ + X_Node_Selector__fetchElements( list, _xnodes, tag, merge ); + }; }; }; }; - +/* + function X_Node_Selector__fetchElements( list, parent, tag, merge ){ + + var xnodes = parent[ '_xnodes' ], + memory = { + i : 0, + l : xnodes.length, + xnodes : xnodes + }, + memories = [ memory ], + i, l, xnode, + uid, _xnodes; + + while( memories.length ){ + memory = memories.pop(); + xnodes = memory.xnodes; + i = memory.i; + l = memory.l; + for( ; i < l; ++i ){ + xnode = xnodes[ i ]; + uid = xnode[ '_uid' ]; + if( !merge[ uid ] && xnode[ '_tag' ] ){ + if( !tag || xnode[ '_tag' ] === tag ) list[ list.length ] = xnode; + + if( _xnodes = xnode[ '_xnodes' ] ){ + if( 1 < _xnodes.length || ( _xnodes[ 0 ] && _xnodes[ 0 ][ '_tag' ] ) ){ + memory.i = i + 1; + memory.l = l; + memory.xnodes = xnodes; + memories[ memories.length ] = memory; + memories[ memories.length ] = { + i : 0, + l : _xnodes.length, + xnodes : _xnodes + }; + merge[ uid ] = true; + break; + }; + }; + }; + merge[ uid ] = true; + }; + }; + }; + */ function X_Node_Selector__funcSelectorChild( type, flag_all, flags, xnodes ){ var res = [], flag_not = flags.not, @@ -658,8 +701,7 @@ function X_Node_Selector__parse( query, last ){ return res; }; function X_Node_Selector__funcSelectorNth( pointer, sibling, flag_all, flags, xnodes, a, b ){ - var _data = funcData, - res = [], + var res = [], checked = {}, flag_not = flags.not, i = 0, n = -1, uid, diff --git a/0.6.x/js/02_dom/22_XTreeBuilder.js b/0.6.x/js/02_dom/22_XTreeBuilder.js index ed57307..09d371e 100644 --- a/0.6.x/js/02_dom/22_XTreeBuilder.js +++ b/0.6.x/js/02_dom/22_XTreeBuilder.js @@ -405,7 +405,7 @@ X_TEMP.bindElementToXnode = if( elm.nodeType !== 3 ){ if( !( text = xnode[ '_text' ] ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){ console.log( '[' +parent[ '_tag' ] + '> UID:' + xnode[ '_uid' ] + ' len:' + xnode[ '_text' ].length + ' code : ' + xnode[ '_text' ].charCodeAt( 0 ) + ',' + xnode[ '_text' ].charCodeAt( 1 ) + '] destroyed.' ); - xnode.destroy(); + xnode[ 'kill' ](); break; }; alert( parent[ '_tag' ] + ' > ' + '"' + xnode[ '_text' ] + '" !== ' + tag + '\n' + @@ -424,12 +424,12 @@ X_TEMP.bindElementToXnode = if( !skipCleanup ){ if( !( text = xnode[ '_text' ] ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){ console.log( '[' +parent[ '_tag' ] + '>' + xnode[ '_uid' ] + '] destroy ... ' ); - xnode.destroy(); + xnode[ 'kill' ](); }; if( xtext ){ xtext[ 'text' ]( xtext[ '_text' ] + text ); console.log( '[' +parent[ '_tag' ] + '>' + xnode[ '_uid' ] + '] xtext,destroy ... ' ); - xnode.destroy(); + xnode[ 'kill' ](); } else { //alert( parent[ '_tag' ] + '>' + '"' + text + '"\n' + elm.data ); xnode[ 'text' ]( text ); @@ -438,7 +438,7 @@ X_TEMP.bindElementToXnode = if( xtext ){ xtext[ 'text' ]( xtext[ '_text' ] + xnode[ '_text' ] ); console.log( '[' +parent[ '_tag' ] + '>' + xnode[ '_uid' ] + '] xtext,destroy ... ' ); - xnode.destroy(); + xnode[ 'kill' ](); }; current.xtext = xtext || xnode; break; @@ -460,13 +460,13 @@ X_TEMP.bindElementToXnode = //alert( X_String_cleanupWhiteSpace( xnode[ '_text' ] ) ); if( !skipCleanup ){ if( !( text = xnode[ '_text' ] ) || ( text = X_String_cleanupWhiteSpace( text ) ) === ' ' ){ - xnode.destroy(); + xnode[ 'kill' ](); xnode = null; } else if( xtext ){ //alert( 'xtext ' + text.charCodeAt( 0 ) + ' : ' + text.length ); xtext[ 'text' ]( xtext[ '_text' ] + text ); - xnode.destroy(); + xnode[ 'kill' ](); } else { //alert( 'xnode ' + text.charCodeAt( 0 ) + ' : ' + text.length ); xnode[ 'text' ]( text ); @@ -475,7 +475,7 @@ X_TEMP.bindElementToXnode = if( xtext ){ //alert( 'skip ' + text.charCodeAt( 0 ) + ' : ' + text.length ); xtext[ 'text' ]( xtext[ '_text' ] + xnode[ '_text' ] ); - xnode.destroy(); + xnode[ 'kill' ](); }; }; current.xtext = xtext || xnode; @@ -503,7 +503,7 @@ X_TEMP.bindElementToXnode = xnode[ '_flags' ] &= X_Node_BitMask_RESET_DIRTY; //xnode[ '_tag' ] = X_Dom_DTD_TAG_FIX[ tag ] || tag; if( X_TEMP._isCleanupTarget( elm ) ){ //!xnode[ 'hasClass' ]( 'skip-cleanup' ) && ( X_Dom_DTD_CLEANUP_TAGS[ tag ] || xnode[ 'hasClass' ]( 'cleanup-target' ) ) ){ - xnode.destroy(); + xnode[ 'kill' ](); break; }; diff --git a/0.6.x/js/05_util/01_XNinjaIframe.js b/0.6.x/js/05_util/01_XNinjaIframe.js index b4ede0f..2eeaaa9 100644 --- a/0.6.x/js/05_util/01_XNinjaIframe.js +++ b/0.6.x/js/05_util/01_XNinjaIframe.js @@ -4,13 +4,11 @@ */ // TODO Node.inherits -X[ 'Util' ][ 'NinjaIframe' ] = X_EventDispatcher[ 'inherits' ]( +X[ 'Util' ][ 'NinjaIframe' ] = Node[ 'inherits' ]( 'NinjaIframe', { autoRefresh : 0, - xnodeIframe : null, - _iwin : null, _contentHTML : '', @@ -22,8 +20,10 @@ X[ 'Util' ][ 'NinjaIframe' ] = X_EventDispatcher[ 'inherits' ]( this._name = 'hidden-iframe-' + X_Timer_now(); // https://github.com/polygonplanet/Pot.js/blob/master/src/Worker.js - this.xnodeIframe = X_Node_body[ 'create' ]( - 'iframe', + X_Node_newByTag = true; + + this[ 'Super' ]( + 'IFRAME', { className : 'hidden-iframe', scrolling : 'no', @@ -35,64 +35,25 @@ X[ 'Util' ][ 'NinjaIframe' ] = X_EventDispatcher[ 'inherits' ]( } ); - X_ViewPort[ 'listenOnce' ]( X_EVENT_AFTER_UPDATE, this ); - // http://nanto.asablo.jp/blog/2011/12/08/6237308 // IE 6/7 で文書間通信を実現するための一案 if( X_UA[ 'IE' ] < 9 ){ - this.xnodeIframe[ 'attr' ]( 'src', 'about:blank' ); + this[ 'attr' ]( 'src', 'about:blank' ); }; // Safari 2.0.* bug: iframe's absolute position and src set. if( !X_UA[ 'Webkit' ] ){ - this.xnodeIframe[ 'css' ]( { position : 'absolute' } ); + this[ 'css' ]( { position : 'absolute' } ); }; - if( html ) this._contentHTML = html; - }, - - 'handleEvent' : function( e ){ - var raw = this.xnodeIframe[ '_rawObject' ]; + if( html ) this._contentHTML = html; - switch( e.type ){ - case X_EVENT_AFTER_UPDATE : - this._iwin = raw.contentWindow || ( raw.contentDocument && raw.contentDocument.parentWindow ) || window.frames[ this._name ]; - // http://d.hatena.ne.jp/NeoCat/20080921/1221940658 - // こちらに名前をsetしないとtargetが動作しない - if( X_UA[ 'IE' ] ) this._iwin.name = this._name; - - this.xnodeIframe[ 'listen' ]( [ X_UA[ 'IE' ] < 9 ? 'readystatechange' : 'load', 'error' ], this ); - - if( !( X_UA[ 'IE' ] < 9 ) ){ - this._contentHTML && X_Util_NinjaIframe_writeToIframe( this ); - this._ready = true; - return; - }; - //break; これあると IE8 で駄目! - - case 'readystatechange' : - if( ( raw.readyState !== 'complete' && raw.readyState !== 'loaded' ) ) break; - // ie9- - if( !this._ready ){ - this._contentHTML && X_Util_NinjaIframe_writeToIframe( this ); - this._ready = true; - break; - }; - // onload - case 'load' : - console.log( 'iframe load.' ); - this[ 'asyncDispatch' ]( X_EVENT_SUCCESS ); - break; - - case 'error' : - this[ 'asyncDispatch' ]( X_EVENT_ERROR ); - break; - }; + this[ 'appendTo' ]( X_Node_body /* X_Node_systemNode */ ); - return X_Callback_STOP_PROPAGATION; + X_ViewPort[ 'listenOnce' ]( X_EVENT_AFTER_UPDATE, this, X_Util_NinjaIframe_handleEvent ); }, 'refresh' : function( opt_contentHTML ){ - var raw = this.xnodeIframe[ '_rawObject' ], + var raw = this[ '_rawObject' ], idoc; this._ready = false; @@ -117,16 +78,58 @@ X[ 'Util' ][ 'NinjaIframe' ] = X_EventDispatcher[ 'inherits' ]( }, 'close' : function(){ - X_ViewPort[ 'unlisten' ]( X_EVENT_AFTER_UPDATE, this ); - this.xnodeIframe.call( 'close' ); - this.xnodeIframe.destroy(); + X_ViewPort[ 'unlisten' ]( X_EVENT_AFTER_UPDATE, this, X_Util_NinjaIframe_handleEvent ); + this.call( 'close' ); + this[ 'kill' ](); } } ); + +function X_Util_NinjaIframe_handleEvent( e ){ + var raw = this[ '_rawObject' ]; + + switch( e.type ){ + case X_EVENT_AFTER_UPDATE : + this._iwin = raw.contentWindow || ( raw.contentDocument && raw.contentDocument.parentWindow ) || window.frames[ this._name ]; + // http://d.hatena.ne.jp/NeoCat/20080921/1221940658 + // こちらに名前をsetしないとtargetが動作しない + if( X_UA[ 'IE' ] ) this._iwin.name = this._name; + + this[ 'listen' ]( [ X_UA[ 'IE' ] < 9 ? 'readystatechange' : 'load', 'error' ], this, X_Util_NinjaIframe_handleEvent ); + + if( !( X_UA[ 'IE' ] < 9 ) ){ + this._contentHTML && X_Util_NinjaIframe_writeToIframe( this ); + this._ready = true; + return; + }; + //break; これあると IE8 で駄目! + + case 'readystatechange' : + if( ( raw.readyState !== 'complete' && raw.readyState !== 'loaded' ) ) break; + // ie9- + if( !this._ready ){ + this._contentHTML && X_Util_NinjaIframe_writeToIframe( this ); + this._ready = true; + break; + }; + // onload + case 'load' : + console.log( 'iframe load.' ); + this[ 'asyncDispatch' ]( X_EVENT_SUCCESS ); + break; + + case 'error' : + this[ 'asyncDispatch' ]( X_EVENT_ERROR ); + break; + }; + + return X_Callback_STOP_PROPAGATION; +}; + function X_Util_NinjaIframe_writeToIframe( that ){ - var raw = that.xnodeIframe[ '_rawObject' ], + var raw = that[ '_rawObject' ], idoc = raw.contentDocument || that._iwin.document, html = that._contentHTML; diff --git a/0.6.x/js/05_util/03_XUtilImage.js b/0.6.x/js/05_util/03_XUtilImage.js index cd5e1d9..a9dcd7f 100644 --- a/0.6.x/js/05_util/03_XUtilImage.js +++ b/0.6.x/js/05_util/03_XUtilImage.js @@ -89,7 +89,7 @@ function X_Util_Image_getActualDimension( XnodeOrImageElemOrSrc ){ ret = X_Util_Image_actualSize[ img.src ] = [ w, h ]; - remove && xnode.destroy(); + remove && xnode[ 'kill' ](); return ret; }; diff --git a/0.6.x/js/06_net/02_XNetJSONP.js b/0.6.x/js/06_net/02_XNetJSONP.js index 6c008f0..21d5e36 100644 --- a/0.6.x/js/06_net/02_XNetJSONP.js +++ b/0.6.x/js/06_net/02_XNetJSONP.js @@ -182,7 +182,7 @@ function X_NET_JSONP_iframeListener( e ){ X_NET_JSONPWrapper[ 'asyncDispatch' ]( X_EVENT_ERROR ); break; }; - X_NET_JSONP_NinjaIframe[ 'unlisten' ](); + X_EventDispatcher_unlistenAll( X_NET_JSONP_NinjaIframe ); return X_Callback_UN_LISTEN; }; diff --git a/0.6.x/js/06_net/04_XNetImage.js b/0.6.x/js/06_net/04_XNetImage.js index 86bbee3..9f5be7a 100644 --- a/0.6.x/js/06_net/04_XNetImage.js +++ b/0.6.x/js/06_net/04_XNetImage.js @@ -86,7 +86,7 @@ X_NET_ImageWrapper = X_Class_override( break; case X_EVENT_KILL_INSTANCE : this.reset(); - !X_Net_Image_hasImage && this.destroy(); // if xnode + !X_Net_Image_hasImage && this[ 'kill' ](); // if xnode break; }; }, diff --git a/0.6.x/js/07_audio/00_XAudio.js b/0.6.x/js/07_audio/00_XAudio.js index edd2dec..acae436 100644 --- a/0.6.x/js/07_audio/00_XAudio.js +++ b/0.6.x/js/07_audio/00_XAudio.js @@ -93,18 +93,18 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ]( return backend ? backend.state() : { - startTime : -1, - endTime : -1, - loopStartTime : -1, - loopEndTime : -1, - currentTime : -1, - loop : false, - looded : false, - error : false, - playing : false, + 'startTime' : -1, + 'endTime' : -1, + 'loopStartTime' : -1, + 'loopEndTime' : -1, + 'currentTime' : -1, + 'loop' : false, + 'looded' : false, + 'error' : false, + 'playing' : false, - source : this[ 'source' ] || '', - duration : 0 + 'source' : this[ 'source' ] || '', + 'duration' : 0 }; }; backend && backend.state( obj ); diff --git a/0.6.x/js/07_audio/03_XSilverlightAudio.js b/0.6.x/js/07_audio/03_XSilverlightAudio.js index c2a113b..f4b84ab 100644 --- a/0.6.x/js/07_audio/03_XSilverlightAudio.js +++ b/0.6.x/js/07_audio/03_XSilverlightAudio.js @@ -236,7 +236,7 @@ if( X[ 'Pulgin' ][ 'SilverlightEnabled' ] ){ delete this._onload; X_Callback_correct( this._callback ); }; - this.xnodeObject.destroy(); + this.xnodeObject[ 'kill' ](); break; }; }, diff --git a/0.6.x/js/07_audio/10_XAudioSprite.js b/0.6.x/js/07_audio/10_XAudioSprite.js index 45caa32..3b9366e 100644 --- a/0.6.x/js/07_audio/10_XAudioSprite.js +++ b/0.6.x/js/07_audio/10_XAudioSprite.js @@ -304,10 +304,22 @@ X_Audio_Sprite_members = { }, state : function( uid, opt_obj ){ - var track = X_Audio_Sprite_TEMP.tracks[ uid ]; + var track = X_Audio_Sprite_TEMP.tracks[ uid ], + state, start, end; // TODO uid = 0 if( opt_obj === undefined ){ - return track ? track.state() : { volume : X_Audio_Sprite_TEMP.volume }; + // TODO pause + if( track ){ + state = track.state(); + start = state.startTime; + return { + 'currentTime' : state.currentTime - state.startTime, + 'playing' : state.startTime <= state.currentTime && state.currentTime <= state.endTime, + 'duration' : state.endTime - state.startTime, + 'volume' : X_Audio_Sprite_TEMP.volume + }; + }; + return { 'volume' : X_Audio_Sprite_TEMP.volume, 'playing' : false }; }; track && track.state( opt_obj ); return this; diff --git a/0.6.x/js/20_ui/06_AbstractUINode.js b/0.6.x/js/20_ui/06_AbstractUINode.js index 62c9043..13af1bc 100644 --- a/0.6.x/js/20_ui/06_AbstractUINode.js +++ b/0.6.x/js/20_ui/06_AbstractUINode.js @@ -386,7 +386,7 @@ X.UI._AbstractUINode = X_EventDispatcher[ 'inherits' ]( case 2: case 1: - this.xnode.destroy(); + this.xnode[ 'kill' ](); delete this.root; delete this.rootData; diff --git a/0.6.x/js/20_ui/20_PageRoot.js b/0.6.x/js/20_ui/20_PageRoot.js index 8b567a8..43fbb74 100644 --- a/0.6.x/js/20_ui/20_PageRoot.js +++ b/0.6.x/js/20_ui/20_PageRoot.js @@ -2,7 +2,7 @@ var X_UI_rootData = null, X_UI_eventBusy = false; function X_UI_eventRellay( e ){ - var font = X.ViewPort.getBaseFontSize(), + var font = X[ 'ViewPort' ][ 'getBaseFontSize' ](), x = e.clientX / font, y = e.clientY / font, type = X.UI.Event.NameToID[ e.type ], @@ -145,8 +145,8 @@ X.UI._PageRoot = X.UI._Box.inherits( }; }, calculate : function( e ){ - var size = X.ViewPort.getSize(), - font = X.ViewPort.getBaseFontSize(), + var size = X[ 'ViewPort' ][ 'getSize' ](), + font = X[ 'ViewPort' ][ 'getBaseFontSize' ](), w = size[ 0 ], h = size[ 1 ]; this.layout.calculate( this, false, 0, 0, w / font, h / font ); @@ -158,7 +158,7 @@ X.UI._PageRoot = X.UI._Box.inherits( }, _remove : function(){ - this.xnodeInteractiveLayer[ 'unlisten' ](); + X_EventDispatcher_unlistenAll( this.xnodeInteractiveLayer ); _Box.prototype._remove.call( this ); } } -- 2.11.0