OSDN Git Service

Version 0.6.185, fix X.AudioSprite & X_Node_onKill.
authoritozyun <itozyun@user.sourceforge.jp>
Thu, 29 Oct 2015 05:38:02 +0000 (14:38 +0900)
committeritozyun <itozyun@user.sourceforge.jp>
Thu, 29 Oct 2015 05:38:02 +0000 (14:38 +0900)
0.6.x/js/01_core/13_XClass.js
0.6.x/js/02_dom/04_XBoxModel.js
0.6.x/js/02_dom/06_XNodeCSS.js
0.6.x/js/02_dom/20_XNode.js
0.6.x/js/07_audio/01_XWebAudio.js
0.6.x/js/07_audio/02_XHTMLAudio.js
0.6.x/js/07_audio/10_XAudioSprite.js

index f5cdc03..bf86574 100644 (file)
@@ -581,7 +581,7 @@ function X_Class_actualConstructor( f, args ){
                                X_Class_useObjectCreate ?\r
                                        Object.create( klass.prototype ) :\r
                                        new klass( X_Closure_COMMAND_DROP );\r
-       \r
+\r
        def.live && def.live.push( instance );\r
 \r
        if( ( X_UA[ 'AOSP' ] < 3 || X_UA[ 'iOS' ] < 5 ) && instance.constructor !== klass ){\r
index 37391ce..ad62c8d 100644 (file)
@@ -65,7 +65,7 @@ X_ViewPort[ 'listenOnce' ]( X_EVENT_INIT, function(){
 function X_Node_BoxModel_mesure( that, name ){\r
        var flags = that[ '_flags' ], elm;\r
        \r
-       if( ( flags & X_NodeFlags_IN_TREE ) === 0 || flags & X_NodeFlags_STYLE_IS_DISPLAY_NONE ) return 0;\r
+       if( ( ( flags & X_NodeFlags_IN_TREE ) === 0 ) || ( flags & X_NodeFlags_STYLE_IS_DISPLAY_NONE ) ) return 0;\r
        \r
        X_Node_updateTimerID && X_Node_startUpdate();\r
        \r
@@ -223,7 +223,7 @@ function X_Node_offset( xnode ){
                offset = { x : 0, y : 0 },\r
                obj, parent, elm;\r
        \r
-       if( ( flags & X_NodeFlags_IN_TREE ) === 0 || flags & X_NodeFlags_STYLE_IS_DISPLAY_NONE ) return offset;\r
+       if( ( ( flags & X_NodeFlags_IN_TREE ) === 0 ) || ( flags & X_NodeFlags_STYLE_IS_DISPLAY_NONE ) ) return offset;\r
        \r
        if( X_Node_body === this || X_Node_html === this ) return offset;\r
 \r
index a74eb98..4938a3a 100644 (file)
@@ -639,7 +639,7 @@ function X_Node_CSS_setStyle( css, flags, name, newValue ){
 function X_Node_cssText( v ){
        var obj, i, l, attr, name;
        
-       if( v === this[ '_cssText' ] && ( this[ '_flags' ] & X_NodeFlags_OLD_CSSTEXT ) === 0 ){
+       if( v === this[ '_cssText' ] && ( ( this[ '_flags' ] & X_NodeFlags_OLD_CSSTEXT ) === 0 ) ){
                return this;
        };      
        
index c303b3d..ca28821 100644 (file)
@@ -9,7 +9,6 @@
 var    Node = X[ 'Node' ] = X_EventDispatcher[ 'inherits' ](
        'X.Node',
        X_Class.POOL_OBJECT,
-       
        {
                /**
                 * 要素に振られるユニークID
@@ -768,10 +767,11 @@ function X_Node_swap( v ){
 };
 
 /**
- * 要素を抜く。
+ * 要素を親要素から抜く。jQuery の remove と異なり、インスタンスは破壊(kill)されず、再び別の親に挿入等できる
  * @alias Node.prototype.remove
  * @return {Node} 自身。チェインメソッド
  * @example node.remove();
+ * parent.append( node ); 新しい親に追加できる
  */
 function X_Node_remove(){
        var parent = this.parent,
@@ -821,7 +821,9 @@ function X_Node_remove(){
  */
 function X_Node_empty(){
        var xnodes = this[ '_xnodes' ], i;
+       
        if( xnodes && ( i = xnodes.length ) ){
+               delete this[ '_xnodes' ];
                for( ; i; ){
                        xnodes[ --i ][ 'kill' ]();
                };
@@ -836,18 +838,20 @@ function X_Node_onKill( that ){
        
        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 ){
@@ -860,7 +864,7 @@ function X_Node_onKill( that ){
        } else {
                if( elm && elm.parentNode && elm.parentNode.tagName ){
                        X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = elm;
-                       X_Node_reserveUpdate();         
+                       X_Node_reserveUpdate();
                };
        };
 };
@@ -1095,7 +1099,12 @@ function X_Node_html( html ){
        // 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
index e33630b..c29e0a4 100644 (file)
@@ -82,6 +82,9 @@ var X_WebAudio_context      = // 4s 以下ではない iPad 2G または iPad mi
                                                                !X_UA[ 'iPhone_4s' ]  && !X_UA[ 'iPad_2Mini1' ]  && !X_UA[ 'iPod_4' ]  &&
                                                                // Android2 + Gecko で WebAudio が極めて不安定
                                                                !( X_UA[ 'Fennec' ] && X_UA[ 'Android' ] < 3 ) &&
+                                                               // AOSP でも WebAudio を不完全に実装するものがある
+                                                               !X_UA[ 'AOSP' ] && !( X_UA[ 'ChromeWV' ] < 5 ) &&
+                                                               !X_UA[ 'Blink' ] &&
                                                                // Firefox40.0.5 + Windows8 で音声が途中から鳴らなくなる
                                                                // Firefox41.0.1 + Windows8 で音声が途中から鳴らなくなる
                                                                !( 40 <= X_UA[ 'Gecko' ] && X_UA[ 'Gecko' ] < 42 && X_UA[ 'Windows' ] ) &&
@@ -196,7 +199,7 @@ if( X_WebAudio_context ){
                                        i    = list.indexOf( webAudio );
                                if( 0 < i ){
                                        list.splice( i, 1 );
-                                       if( list.length ){
+                                       if( !list.length ){
                                                this.xhr && this.xhr[ 'kill' ]();
                                                this[ 'kill' ]();
                                        };
@@ -300,9 +303,7 @@ if( X_WebAudio_context ){
                        this.audioBuffer = buffer;
                        this.duration    = buffer.duration * 1000;
 
-                                       this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );
-                       
-                       console.log( 'WebAudio buffer ready' );
+                                       this.disatcher[ 'asyncDispatch' ]( X_WebAudio_touchState ? X_EVENT_MEDIA_TOUCH_FOR_LOAD : X_EVENT_READY );
                                },
                        
                        actualPlay : function(){
@@ -321,6 +322,7 @@ if( X_WebAudio_context ){
                                                // alert( 'タッチイベント以外での play! ' + ( e ? e.type : '' ) );
                                                return;
                                        };
+                                       this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );
                                };
                                X_WebAudio_touchState = false;
                                
index 786f343..30b2794 100644 (file)
@@ -65,11 +65,12 @@ var
        X_HTMLAudio_pauseFix            = 12 <= X_UA[ 'Opera' ] && 0 < ' XP XPSP2 2003|XP64'.indexOf( X_UA[ 'Windows' ] ), // XP + Opera12 のみ?\r
 \r
        X_HTMLAudio_need1stTouch        = X_UA[ 'iOS' ] || 4.2 <= X_UA[ 'AOSP' ] || X_UA[ 'ChromeWV' ] || X_UA[ 'WinPhone' ] || ( X_UA[ 'Blink' ] && X_UA[ 'Android' ] ),\r
-       \r
+\r
        X_HTMLAudio_playTrigger     = ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) ? 'canplay' : X_UA[ 'iOS' ] ? 'suspend' : X_UA[ 'Blink' ] ? 'stalled' : 'canplaythrough',\r
-       \r
-       X_HTMLAudio_durationFix     = X_UA[ 'iOS' ] || X_UA[ 'ChromeWV' ] || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) || ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] ),\r
-       \r
+\r
+       X_HTMLAudio_durationFix     = X_UA[ 'iOS' ] || X_UA[ 'ChromeWV' ] || ( X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ] ) ||\r
+                                                               ( X_UA[ 'Windows' ] && 12 <= X_UA[ 'Opera' ] ) || ( X_UA[ 'Blink' ] && X_UA[ 'Android' ] ),\r
+\r
        X_HTMLAudio_shortPlayFix        = X_UA[ 'AOSP' ]; // Android 4.1.1 でも遭遇\r
 \r
 if( X_Audio_constructor ){\r
@@ -78,8 +79,6 @@ if( X_Audio_constructor ){
                'X.HTMLAudio',\r
                X_Class.POOL_OBJECT,\r
                {\r
-                       _closed               : true,\r
-\r
                        // 1: canplaythrought|timeupdateに達している、またはdurationFixが終了している\r
                        // 2: READY イベント発火済\r
                        _readyState       : 0,\r
@@ -111,7 +110,6 @@ if( X_Audio_constructor ){
                                var raw;\r
                                \r
                                this.disatcher = disatcher || this;\r
-                               this._closed   = false;\r
                                this._src          = source;\r
                                \r
                                if( X_HTMLAudio_shortPlayFix ){\r
@@ -192,14 +190,13 @@ if( X_Audio_constructor ){
                                        ready,\r
                                        eventType, duration, end, now;\r
                                \r
-                               if( this._closed ) return;\r
+                               if( !raw ) return;\r
 \r
                                //e.type !== 'timeupdate' && console.log( ' > ' + e.type );\r
                                        \r
                                switch( e.type ){\r
 \r
                                        case X_EVENT_KILL_INSTANCE :\r
-                                               delete this._closed;\r
                                                this.playing && this.actualPause();\r
                                                \r
                                                // 【javascript】モバイル向けブラウザでも音を鳴らしたい【WebAudio】\r
@@ -233,7 +230,7 @@ if( X_Audio_constructor ){
                                                        this._readyState |= 1;\r
                                                };\r
                                        case 'canplay' :                //      今すぐに再生を再開できるが、バッファリングが不十分でコンテンツを最後まで表示できないと予測している場合に発生\r
-                                               if( this._durationFixPhase === 1 && !X_HTMLAudio_need1stTouch ){\r
+                                               if( this._durationFixPhase === 1 && !X_HTMLAudio_need1stTouch ){ // PC Opera12 用 durationFix\r
                                                        this._durationFixPhase = 2;\r
                                                        this.actualPlay();\r
                                                        raw.currentTime = 0; // Win8 + Opera12 で必要\r
@@ -324,7 +321,8 @@ if( X_Audio_constructor ){
                                };\r
                                \r
                                // duration は Infinity, NaN, 0 の場合があるため、これを除外する\r
-                               if( 0 < duration && X_Type_isFinite( duration ) ){\r
+                               // chrome18 for Android は duration = 100 の間はシークができない? 28 は可能\r
+                               if( 0 < duration && X_Type_isFinite( duration ) && duration !== 100 ){\r
                                        this.duration = duration * 1000;\r
 \r
                                        if( this._durationFixPhase === 4 ){\r
@@ -333,7 +331,6 @@ if( X_Audio_constructor ){
                                                \r
                                                if( this.autoplay || this._playReserved ){\r
                                                        console.log( '☆ 再生 <- DurationFix の終了' );\r
-                                                       delete this._playReserved;\r
                                                        this.actualPlay();\r
                                                } else\r
                                                if( X_HTMLAudio_pauseFix ){\r
@@ -367,7 +364,7 @@ if( X_Audio_constructor ){
                                        };\r
                                } else\r
                                if( this._readyState === 1 && this.duration ){\r
-                                       this._readyState = 3;\r
+                                       this._readyState = 2;\r
                                        this.disatcher[ 'asyncDispatch' ]( X_EVENT_READY );\r
                                        console.log( '> Audio Loaded!! ' + e.type + ' d:' + ( this.duration | 0 ) );\r
                                } else\r
@@ -380,13 +377,20 @@ if( X_Audio_constructor ){
                                var raw = this[ '_rawObject' ],\r
                                        e, begin, end;\r
 \r
-                               if( this._closed ) return;\r
+                               if( !raw ) return;\r
                                \r
-                               if( !raw.src ){ // X_HTMLAudio_pauseFix によって src が空になっている\r
-                                       console.log( '○ 削除された audio.src の復帰' );\r
-                                       raw.src = this._src;\r
-                                       return;\r
-                               };                              \r
+                               this._playReserved = true;\r
+                               \r
+                               if( X_HTMLAudio_pauseFix ){\r
+                                       if( !raw.src ){ // X_HTMLAudio_pauseFix によって src が空になっている\r
+                                               console.log( '○ 削除された audio.src の復帰' );\r
+                                               raw.src = this._src;\r
+                                               return;\r
+                                       };\r
+                                       if( this._durationFixPhase < 2 ){\r
+                                               return;\r
+                                       };              \r
+                               };\r
 \r
                                if( this._touchState === 2 ){\r
                                        e = X_EventDispatcher_CURRENT_EVENTS[ X_EventDispatcher_CURRENT_EVENTS.length - 1 ];\r
@@ -396,11 +400,12 @@ if( X_Audio_constructor ){
                                        };\r
                                        this._touchState = 3;\r
                                } else\r
-                               if( this._readyState !== 3 && this._durationFixPhase < 2 ){\r
-                                       this._playReserved = true;\r
+                               if( this._readyState !== 2 && this._durationFixPhase < 2 ){\r
                                        return;\r
                                };\r
                                \r
+                               delete this._playReserved;\r
+                               \r
                                if( this._durationFixPhase & 3 ){ // 1 or 2\r
                                        console.log( '▲ DurationFix の開始' );\r
                                        this._durationFixPhase = 4;\r
@@ -432,7 +437,6 @@ if( X_Audio_constructor ){
                                        } else\r
                                        if( X_HTMLAudio_needPlayForSeek || forcePlay ){\r
                                                raw.play();\r
-                                               //console.log( '[HTMLAudio] currentTime より先.' );\r
                                        };\r
                                        \r
                                        //http://himaxoff.blog111.fc2.com/blog-entry-97.html\r
index 763eca7..7754228 100644 (file)
@@ -27,7 +27,8 @@ var X_AudioSprite_shouldUse         = X_HTMLAudio && ( X_UA[ 'iOS' ] || X_UA[ 'A
                bgmPosition : 0,\r
                bgmName     : '',\r
                bgmLooped   : false,\r
-               bgmPlaying  : false\r
+               bgmPlaying  : false,\r
+               event       : null\r
        },\r
        X_AudioSprite,\r
        X_AudioSprite_numTracks,\r
@@ -63,10 +64,11 @@ X[ 'AudioSprite' ] = function( setting ){
                volume  = setting[ 'volume' ],\r
                k, i, v, track;\r
        \r
-       if( !X_AudioSprite ){\r
-               X_AudioSprite = X_Class_override( X_EventDispatcher(), X_AudioSprite_members );\r
-               X_ViewPort[ 'listen' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE, X_EVENT_UNLOAD ], X_AudioSprite, X_AudioSprite_handleEvent );\r
-       };\r
+\r
+       if( X_AudioSprite ) X_AudioSprite[ 'kill' ]();\r
+\r
+       X_AudioSprite = X_Class_override( X_EventDispatcher(), X_AudioSprite_members );\r
+       X_ViewPort[ 'listen' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE, X_EVENT_UNLOAD ], X_AudioSprite_handleEvent );\r
        \r
        n = n <= X_AudioSprite_maxTracks ? n : X_AudioSprite_maxTracks;\r
        \r
@@ -176,7 +178,7 @@ var X_AudioSprite_members =
                                                track = X_AudioSprite_TEMP.bgmTrack = tracks[ 0 ];\r
                                        };\r
                                        \r
-                                       if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite, X_AudioSprite_handleEvent ).playing ){\r
+                                       if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite_handleEvent ).playing ){\r
                                                track.setState({\r
                                                                'loop'          : true,\r
                                                                'looped'        : X_AudioSprite_TEMP.bgmLooped,\r
@@ -196,7 +198,7 @@ var X_AudioSprite_members =
                                        if( 1 < X_AudioSprite_numTracks ){\r
                                                track = X_AudioSprite_getTrackEnded( X_AudioSprite_TEMP.bgmPlaying );\r
                                                track\r
-                                                       [ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite, X_AudioSprite_handleEvent )\r
+                                                       [ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite_handleEvent )\r
                                                        .setState( { 'looped' : false } );\r
                                                track.play( preset[ 0 ], preset[ 1 ], true, 0, X_AudioSprite_lengthSilence );\r
                                        } else {\r
@@ -208,7 +210,7 @@ var X_AudioSprite_members =
                                                };\r
                                                track = tracks[ 0 ];\r
                                        \r
-                                               if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite, X_AudioSprite_handleEvent ).playing ){\r
+                                               if( track[ 'listen' ]( [ X_EVENT_MEDIA_PLAYING, X_EVENT_MEDIA_WAITING, X_EVENT_MEDIA_SEEKING, X_EVENT_MEDIA_BEFORE_LOOP ], X_AudioSprite_handleEvent ).playing ){\r
                                                        track.setState({\r
                                                                        'loop'          : true,\r
                                                                        'looped'        : false,\r
@@ -219,7 +221,6 @@ var X_AudioSprite_members =
                                                                        'loopEndTime'   : X_AudioSprite_lengthSilence\r
                                                                });\r
                                                } else {\r
-                                                       \r
                                                        track.play( preset[ 0 ], preset[ 1 ], true, 0, X_AudioSprite_lengthSilence );   \r
                                                };\r
                                        };\r
@@ -352,7 +353,7 @@ function X_AudioSprite_backendHandler( e ){
                                };\r
                                // Audiobackend の owner として null を渡すとAudioBackend 自身へ dispatch する\r
                                X_AudioSprite_TEMP.tracks.push(\r
-                                       last = backend.klass( null, e[ 'source' ], option )[ 'listen' ]( X_EVENT_DEBUG, X_AudioSprite, X_AudioSprite_handleEvent ) );\r
+                                       last = backend.klass( null, e[ 'source' ], option )[ 'listen' ]( X_EVENT_DEBUG, X_AudioSprite_handleEvent ) );\r
                        };\r
 \r
                        _e = {\r
@@ -360,26 +361,36 @@ function X_AudioSprite_backendHandler( e ){
                                'source'      : src,\r
                                'backendName' : name\r
                        };\r
-                       // touch 可能で backend ready\r
-                       // WebAudio\r
-                       if( backend.backendID === 1 && ( _e[ 'needTouchForPlay' ] = X_WebAudio_need1stTouch ) ){\r
-                               last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite, X_AudioSprite[ 'asyncDispatch' ], [ _e ] );\r
-                       } else\r
-                       // HTMLAudio\r
-                       if( backend.backendID === 2 && ( _e[ 'needTouchForLoad' ] = X_HTMLAudio_need1stTouch ) ){\r
-                               last[ 'listenOnce' ]( X_EVENT_MEDIA_TOUCH_FOR_LOAD, X_AudioSprite, X_AudioSprite[ 'asyncDispatch' ], [ _e ] );\r
+                       \r
+                       // TODO 今は touch 可能で backend ready\r
+                       if(\r
+                               // WebAudio\r
+                               ( backend.backendID === 1 && ( _e[ 'needTouchForPlay' ] = X_WebAudio_need1stTouch  ) ) ||\r
+                               // HTMLAudio\r
+                               ( backend.backendID === 2 && ( _e[ 'needTouchForLoad' ] = X_HTMLAudio_need1stTouch ) )\r
+                       ){\r
+                               X_AudioSprite_TEMP.event = _e;\r
+                               last[ 'listenOnce' ]( X_EVENT_MEDIA_TOUCH_FOR_LOAD, X_AudioSprite_backendHandler );\r
                        } else {\r
                                X_AudioSprite[ 'asyncDispatch' ]( _e );\r
                        };\r
                        \r
-                       last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite, X_AudioSprite_backendHandler );\r
+                       // TODO 全ての track の READY で!\r
+                       last[ 'listenOnce' ]( X_EVENT_READY, X_AudioSprite_backendHandler );\r
                        return X_CALLBACK_STOP_NOW;\r
 \r
                case X_EVENT_BACKEND_NONE :\r
-                       X_AudioSprite[ 'unlisten' ]( X_EVENT_BACKEND_READY, X_AudioSprite, X_AudioSprite_backendHandler )\r
+                       X_AudioSprite\r
+                               [ 'listen' ]( X_EVENT_BACKEND_NONE, X_AudioSprite_handleEvent ) // kill を呼ぶ\r
                                [ 'asyncDispatch' ]( X_EVENT_BACKEND_NONE );\r
                        return X_CALLBACK_STOP_NOW;\r
                \r
+               case X_EVENT_MEDIA_TOUCH_FOR_LOAD :\r
+                       // TODO 全ての track の MEDIA_TOUCH_FOR_LOAD で!\r
+                       X_AudioSprite[ 'asyncDispatch' ]( X_AudioSprite_TEMP.event );\r
+                       delete X_AudioSprite_TEMP.event;\r
+                       break;\r
+               \r
                case X_EVENT_READY :\r
                        console.log( 'X.AudioSprite - Ready!' );\r
                        for( i = 0; i < X_AudioSprite_numTracks; ++i ){\r
@@ -394,23 +405,21 @@ function X_AudioSprite_backendHandler( e ){
 \r
 \r
 function X_AudioSprite_handleEvent( e ){\r
-       var i, tracks, track, _e, k;\r
+       var track = e.target, i, tracks, _e, k;\r
        \r
        switch( e.type ){\r
                case X_EVENT_MEDIA_PLAYING :\r
-                       ( e.target === X_AudioSprite_TEMP.bgmTrack || !e.target.looped ) &&  X_AudioSprite[ 'asyncDispatch' ]( X_EVENT_MEDIA_PLAYING );\r
-                       break;\r
                case X_EVENT_MEDIA_WAITING :\r
                case X_EVENT_MEDIA_SEEKING :\r
-                       ( e.target === X_AudioSprite_TEMP.bgmTrack || !e.target.looped ) &&  X_AudioSprite[ 'asyncDispatch' ]( e.type );\r
+                       ( track === X_AudioSprite_TEMP.bgmTrack || !track.looped ) &&  X_AudioSprite[ 'asyncDispatch' ]( e.type );\r
                        break;\r
                \r
                case X_EVENT_MEDIA_BEFORE_LOOP :\r
-                       if( e.target === X_AudioSprite_TEMP.bgmTrack ){\r
+                       if( track === X_AudioSprite_TEMP.bgmTrack ){\r
                                X_AudioSprite_TEMP.bgmLooped = true;\r
                                X_AudioSprite[ 'asyncDispatch' ]( X_EVENT_MEDIA_LOOPED ); // TODO uid\r
                        } else {\r
-                               if( e.target.looped ){\r
+                               if( track.looped ){\r
                                        // X_AudioSprite[ 'asyncDispatch' ]( X_EVENT_MEDIA_LOOPED ); // TODO uid\r
                                } else {\r
                                         X_AudioSprite[ 'asyncDispatch' ]( X_EVENT_MEDIA_ENDED ); // TODO uid\r
@@ -420,7 +429,7 @@ function X_AudioSprite_handleEvent( e ){
                                \r
                                // single track | iOS\r
                                if( X_AudioSprite_TEMP.bgmPlaying && !X_AudioSprite_TEMP.bgmTrack ){\r
-                                       X_AudioSprite_TEMP.bgmTrack = e.target;\r
+                                       X_AudioSprite_TEMP.bgmTrack = track;\r
                                        X_AudioSprite.play( X_AudioSprite_TEMP.bgmName );\r
                                        return X_CALLBACK_PREVENT_DEFAULT;\r
                                };\r
@@ -429,7 +438,7 @@ function X_AudioSprite_handleEvent( e ){
                \r
                \r
                case X_EVENT_DEBUG :\r
-                       i = X_AudioSprite_TEMP.tracks.indexOf( e.target );\r
+                       i = X_AudioSprite_TEMP.tracks.indexOf( track );\r
                        if( 0 <= i ){\r
                                e[ 'trackID' ] = i;\r
                                X_AudioSprite[ 'dispatch' ]( e );\r
@@ -455,16 +464,20 @@ function X_AudioSprite_handleEvent( e ){
                        };\r
                        break;\r
                \r
+               case X_EVENT_BACKEND_NONE :\r
                case X_EVENT_UNLOAD :\r
-                       console.log( '■ unload' );\r
+                       X_AudioSprite[ 'kill' ]();\r
+                       break;\r
                \r
                case X_EVENT_KILL_INSTANCE :\r
+                       X_AudioSprite_TEMP.pauseTracks.length = 0;\r
+                       \r
                        while( X_AudioSprite_TEMP.tracks.length ){\r
                                X_AudioSprite_TEMP.tracks.pop()[ 'kill' ]();\r
                        };\r
                        \r
-                       for( k in X_AudioSprite_TEMP.bgms ){\r
-                               delete X_AudioSprite_TEMP.bgms[ k ];\r
+                       for( k in X_AudioSprite_TEMP.BGMs ){\r
+                               delete X_AudioSprite_TEMP.BGMs[ k ];\r
                        };\r
                        for( k in X_AudioSprite_TEMP.presets ){\r
                                delete X_AudioSprite_TEMP.presets[ k ];\r
@@ -476,7 +489,8 @@ function X_AudioSprite_handleEvent( e ){
                        X_AudioSprite_TEMP.bgmLooped   = false;\r
                        X_AudioSprite_TEMP.bgmPlaying  = false;\r
                        \r
-                       X_ViewPort[ 'unlisten' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE, X_EVENT_UNLOAD ],  X_AudioSprite, X_AudioSprite_handleEvent );\r
+                       X_ViewPort[ 'unlisten' ]( [ X_EVENT_VIEW_ACTIVATE, X_EVENT_VIEW_DEACTIVATE, X_EVENT_UNLOAD ], X_AudioSprite_handleEvent );\r
+                       X_AudioSprite = null;\r
                        break;\r
        };\r
 };\r