OSDN Git Service

Version 0.6.132, fix X.Node._flags & fix X.EventDispatcher._listeners & start to...
[pettanr/clientJs.git] / 0.6.x / js / 01_core / 11_XClass.js
index 248b5bd..8fa3773 100644 (file)
@@ -1,19 +1,24 @@
-/**\r
- * Class を定義し システムの管理下に置く.\r
- * 全てのクラスと pool が有効の場合インスタンスへの参照が保持される.\r
- *  1. X.Class.create( opt_settings, opt_name, opt_privateClass, opt_props ) でクラスを登録.\r
- *  2. コンストラクタ となるメソッドは、opt_props 内の Constructor : function( arg ){ ... }, に書く.\r
- *  3. 通常通り new で インスタンス生成\r
- *  4. kill() でオブジェクトをクリーンして削除、pool が有効の場合は pool される.\r
- *  5. pool が有効の場合、new で pool されたインスタンスが返される.\r
- *  6. \r
- * \r
- */\r
 \r
 // ------------------------------------------------------------------------- //\r
 // ------------ local variables -------------------------------------------- //\r
 // ------------------------------------------------------------------------- //\r
-var X_Class_CLASS_LIST         = [],\r
+var\r
+       /**\r
+        * 全てのクラスのスーパークラスのようなもの。(ライブラリ内にカプセル化されているため、ユーザが触ることはありません)<br>\r
+        * X.Class.create() で定義されたクラスのインスタンスが共通で備えるメソッド を確認してください。\r
+        * @class __ClassBase__\r
+        * @private\r
+        * @abstract\r
+        */\r
+       __ClassBase__ = {\r
+                       /**\r
+                        * クラス名\r
+                        * @type {string}\r
+                        */\r
+                       name         : ''\r
+               },\r
+\r
+       X_Class_CLASS_LIST         = [],\r
        X_Class_DEF_LIST           = [],\r
        X_Class_PRIVATE_CLASS_LIST = [],\r
        X_Class_PRIVATE_DEF_LIST   = [],\r
@@ -25,18 +30,19 @@ var X_Class_CLASS_LIST         = [],
        X_Class_use_proto_         = !X_UA.OperaMobile && !X_UA.OperaTablet && !!X.emptyFunction.prototype.__proto__,\r
                // Opera Mobile 12.10 Android11 IS01 でクラスのメンバが欠落する問題に遭遇。__proto__ を使わないと動作,,,\r
 \r
-/** \r
- * X.Class.create で定義されたクラスのインスタンスが共通で備えるメソッド を格納\r
- *\r
- * @class\r
- */ \r
-X_Class_CommonProps =\r
-\r
+X_Class_CommonMethods =\r
+/** @lends __ClassBase__.prototype */\r
 {\r
-       /*\r
-        * インスタンスの破棄。\r
-        * TODO kill したインスタンスのイベントが残っていないか?これは開発用のみ\r
+       /**\r
+        * 全ての動的メンバを削除して、インスタンスを破棄する。<br>\r
+        * インスタンスが X.EventDispatcher とそのサブクラスの場合、次の動作をする。\r
+        * <ol>\r
+        * <li>X.Event.BEFORE_KILL_INSTANCE を発火する。戻り値のビットフラグに X.Callback.PREVENT_DEFAULT が立つ場合、破棄をキャンセルし X.Event.KILL_INSTANCE_CANCELED を発火する。\r
+        * <li>破棄に進む場合は、X.Event.KILL_INSTANCE を発火する。\r
+        * <li>dispatch 中は、インスタンスの全ての dispatch が終了するまで実際の破棄を待つ。\r
+        * <li>実際の破棄では、インスタンスのメンバの削除に加えて全てのイベントリスナを解除する。\r
         */\r
+       // TODO kill したインスタンスのイベントが残っていないか?これは開発用のみ\r
        kill : function(){\r
                var instance = this,\r
                        klass    = X_Class_getClass( instance ),\r
@@ -48,28 +54,30 @@ X_Class_CommonProps =
                };\r
                X_Class_killPrivateFlag = false; // instance.kill() 内で PrivateInstance.kill() を防ぐため\r
                \r
-               // X.EventDispatcher とそのサブクラスは kill() が呼ばれた通知を発行する。\r
-               // X.Event.BEFORE_KILL_INSTANCE はキャンセル可能(private な class は不可)\r
-               // X.Event.KILL_INSTANCE は、プロパティやイベントリスナの削除直前に発行\r
-               // X.Event.KILL_INSTANCE_CANCELED は kill() がキャンセルされた場合に発行。また dispatchループ中にkill()が呼ばれると一旦キャンセルされ発行。\r
-               //   (flagを立ててdispatchの終わりにkillする)\r
                if( this.instanceOf( X.EventDispatcher ) ){\r
                        if( !def.isPrivate ){\r
-                               if( this[ '_listeners' ] && this[ '_listeners' ]._dispatching ){\r
-                                       this.dispatch( X.Event.BEFORE_KILL_INSTANCE );\r
-                                       this[ '_listeners' ]._killReserved = true;\r
-                                       this.dispatch( X.Event.KILL_INSTANCE_CANCELED );\r
-                                       return;\r
-                               } else\r
                                if( this.dispatch( X.Event.BEFORE_KILL_INSTANCE ) & X.Callback.PREVENT_DEFAULT ){\r
                                        this.dispatch( X.Event.KILL_INSTANCE_CANCELED );\r
                                        return;\r
                                };\r
+                               if( this[ '_listeners' ] && this[ '_listeners' ][ X_Listeners_.DISPATCHING ] ){\r
+                                       this[ '_listeners' ][ X_Listeners_.KILL_RESERVED ] = true;\r
+                                       return;\r
+                               };\r
                        } else {\r
                                this.dispatch( X.Event.BEFORE_KILL_INSTANCE );  \r
                        };\r
+\r
+                       // asyncDispatch の削除\r
+                       for( p in X_EventDispatcher_LAZY_TIMERS ){\r
+                               if( X_EventDispatcher_LAZY_TIMERS[ p ] === this ){\r
+                                       delete X_EventDispatcher_LAZY_TIMERS[ p ]; // 削除が先!理由は X.Timer.removeを確認。\r
+                                       X.Timer.remove( parseFloat( p ) );\r
+                               };\r
+                       };\r
+                       \r
                        this.dispatch( X.Event.KILL_INSTANCE );\r
-                       this._listeners && X_EventDispatcher_systemUnlisten( this ); //.unlisten();\r
+                       this._listeners && X_EventDispatcher_systemUnlisten( this );\r
                };\r
                \r
                for( p in instance ){\r
@@ -85,8 +93,8 @@ X_Class_CommonProps =
                        if( i !== -1 ){\r
                                data = X_Class_getPrivate( instance );\r
                                X_Class_killPrivateFlag = true;\r
-                               if( data[ '_listeners' ] && data[ '_listeners' ]._dispatching && data.instanceOf( X.EventDispatcher ) ){\r
-                                       data[ '_listeners' ]._killReserved = true;\r
+                               if( data[ '_listeners' ] && data[ '_listeners' ][ X_Listeners_.DISPATCHING ] && data.instanceOf( X.EventDispatcher ) ){\r
+                                       data[ '_listeners' ][ X_Listeners_.KILL_RESERVED ] = true;\r
                                } else {\r
                                        data.kill();\r
                                };\r
@@ -96,12 +104,17 @@ X_Class_CommonProps =
                };\r
        },\r
        \r
-       /*  クラス定義を辿ってスーパークラスのコンストラクタを探す。\r
-        *  呼び出したコンストラクタは配列に控える。\r
-        *  さらに呼ばれた場合、配列を元にさらに奥のコンストラクタを取得\r
-        *  TODO 現在 new しているインスタンスを保持してチェックする\r
+       /**\r
+        * 関数は Constructor 内で使用します。クラス定義を辿ってスーパークラスのコンストラクタを探します。<br>\r
+        * 内部的には、呼び出したコンストラクタは配列に控え(X_Class_CALLING_SUPER)、呼び出したコンストラクタ内でさらに Super が呼ばれた場合、配列を元にさらにスーパーなコンストラクタを辿ります。\r
+        * @example Constructor : function( arg1, arg2 ){\r
+        *      this.Super( aeg1, arg2 );\r
+        * }\r
+        * @param var_args {...?} 親コンストラクタを呼ぶ際に渡す任意の数の引数\r
+        * @return {*}\r
         */\r
-       Super : function(){\r
+       // TODO 現在 new しているインスタンスを保持してチェックする\r
+       Super : function( var_args ){\r
                var sClass = this,\r
                        i      = X_Class_CALLING_SUPER.indexOf( sClass ),\r
                        n      = -1,\r
@@ -132,18 +145,22 @@ X_Class_CommonProps =
                console.log( 'スーパークラスのコンストラクタが見つかりません' );\r
        },\r
 \r
-       /*\r
-        * func について、親クラスで設定されている同名の関数メンバーを呼び出す\r
-        * 2つ以上の異なる名前で同じ関数がメンバーだった場合、失敗します\r
-        * 例) this.superCall( arguments.callee, param0, param1, ... )\r
+       /**\r
+        * func について、親クラスで設定されている同名の関数メンバーを呼び出す。<br>\r
+        * 第一引数に関数を指定し、2つ以上の異なる名前で同じ関数がメンバーがいた場合、動作が不確実になります。<br>\r
+        * 参考:<a href="http://qiita.com/no22@github/items/d3bead2acbb7ff1fb86b" target="_blank">ES5なJavascriptでモダンなクラス的継承&スーパー呼び出し </a>\r
+        * @param funcNameOrFunc {Function|string} スーパークラスの関数名 または、オーバーライド済の自身の関数。\r
+        * @param var_args {...*} オーバーライド元関数に渡す任意の数の引数\r
+        * @example return this.superCall( arguments.callee, param0, param1, ... );\r
+        * @return {*} オーバーライド元の関数を呼び出した戻り値。\r
         */\r
-       superCall : function( func /* ...args */ ){\r
+       superCall : function( funcNameOrFunc, var_args ){\r
                var sClass = this,\r
                        args   = arguments,\r
                        name, p, sFunc, hit = false;\r
-               if( X.Type.isFunction( func ) ){\r
-                       for( p in this ){\r
-                               if( this[ p ] === func ){\r
+               if( X.Type.isFunction( funcNameOrFunc ) ){\r
+                       for( p in this.constructor.prototype ){\r
+                               if( this.constructor.prototype[ p ] === funcNameOrFunc ){\r
                                        name = p;\r
                                        break;\r
                                };\r
@@ -159,7 +176,7 @@ X_Class_CommonProps =
                        def    = X_Class_getClassDef( sClass );\r
                        sClass = def.SuperClass;\r
                        sFunc  = sClass.prototype[ name ];\r
-                       if( sFunc === func ){\r
+                       if( sFunc === funcNameOrFunc ){\r
                                hit = true; // 現在の関数にヒット\r
                        } else\r
                        if( hit && X_Object_inObject( name, this ) ){\r
@@ -184,9 +201,14 @@ X_Class_CommonProps =
                };\r
        },\r
        \r
-       /*\r
-        * TODO instanceof に対応したブラウザはそちらを使用\r
+       /**\r
+        * インスタンスのクラスか?またはスーパークラスか?調べる。<br>\r
+        * instanceof 構文をサポートしない環境(IE4,Mac IE5)を想定する場合、必ずこのメソッドを使用すること。<br>\r
+        * クラスのインスタンスか?だけ調べたい場合は this.constructor === klass が高速。\r
+        * @param klass {__ClassBase__} クラス定義\r
+        * @return {boolean}\r
         */\r
+       // TODO instanceof に対応したブラウザはそちらを使用\r
        instanceOf : function( klass ){\r
                var Super = this;\r
                if( this.constructor === klass ) return true;\r
@@ -201,32 +223,66 @@ X_Class_CommonProps =
 // --- interface ----------------------------------------------------------- //\r
 // ------------------------------------------------------------------------- //\r
 \r
-/** @namespace */ \r
+/**\r
+ * Class を定義し システムの管理下に置く.<br>\r
+ * 全てのクラスと pool が有効の場合インスタンスへの参照が保持される.\r
+ * <ol>\r
+ * <li>X.Class.create( opt_settings, opt_name, opt_privateClass, opt_props ) でクラスを登録.\r
+ * <li>コンストラクタ となるメソッドは、opt_props 内の Constructor : function( arg ){ ... }, に書く.\r
+ * <li>通常通り new で インスタンス生成\r
+ * <li>kill() でオブジェクトをクリーンして削除、pool が有効の場合は pool される.\r
+ * <li>pool が有効の場合、new で pool されたインスタンスが返される.\r
+ * @namespace X.Class\r
+ * @alias X.Class\r
+ */ \r
 X.Class = {\r
-       \r
+\r
+    /**\r
+     * 設定なし。\r
+     */        \r
        NONE         : 0,\r
        \r
     /**\r
      * インスタンスは破棄時(this.kill())に回収され、次回の new MyClass() 時に再利用されます。\r
-     * @memberof X.Class */\r
+     */\r
        POOL_OBJECT  :  1,\r
        \r
        /**\r
         * 定義するクラスは抽象クラスになります。new AbstractClass() とするとエラーになります。\r
-        * @memberof X.Class */\r
+        */\r
        ABSTRACT     :  2,\r
-       \r
-       \r
-       /** @memberof X.Class */\r
+\r
+       /**\r
+        * クラスの継承を禁止する。\r
+        */\r
        FINAL        :  4,\r
-       /** @memberof X.Class */\r
+\r
+       /**\r
+        * 使用を中止。petanR ライブラリ使用プロジェクトから SUPER_ACCESS を消したらここも削除。\r
+        */\r
        SUPER_ACCESS :  8,\r
-       /** @memberof X.Class */\r
+\r
+       /**\r
+        * 内部コード、主に X.UI フレームワークに対して、フレーム外に露出するインスタンスとペアで動作する、シャドウなインスタンスの使用を宣言する。\r
+        * Javascript はインスタンス毎のカプセル化がとてもコスト高。微妙なコスト増で隠蔽されたインスタンスを使う。\r
+        */\r
        PRIVATE_DATA : 16,\r
-       /** @memberof X.Class */\r
-       SINGLETON    : 32, // 未実装\r
-       \r
-       create : function( /* displayName, classSetting, opt_PrivateClass, props */ ){\r
+\r
+       /**\r
+        * 未実装。でも目印になるので付けておきましょう。\r
+        */\r
+       SINGLETON    : 32,\r
+\r
+       /**\r
+        * クラスを定義する。<br>\r
+        * X.Class.create() によるクラス定義は必ずしもコンストラクタを必要としません。クラス定義時にコンストラクタが未設定の場合、スーパークラスがあればそのコンストラクタを使用します。\r
+        * @param {string} [displayName] クラスの名前\r
+        * @param {number} [classSetting=0] X.Class.POOL_OBJECT | X.Class.FINAL など\r
+        * @param {__ClassBase__=} [privateClass] このクラスとペアで動作するシャドウクラス\r
+        * @param {object} [props={}] このクラスのメンバと関数。コンストラクタは Constructor と書くこと\r
+        * @return {__ClassBase__}\r
+        */\r
+       create : function( /* displayName, classSetting, privateClass, props */ ){\r
                var args        = X_Object_cloneArray( arguments ),\r
                        displayName = args[ 0 ],\r
                        classSetting,\r
@@ -291,7 +347,7 @@ X.Class = {
                klass.subClassOf   = X_Class_subClassOf;\r
                \r
                if( X_Class_useObjectCreate ){\r
-                       klass.prototype = X_Class_override( X_Class_override( X_Class_traits || klass.prototype, props, true ), X_Class_CommonProps, false );\r
+                       klass.prototype = X_Class_override( X_Class_override( X_Class_traits || klass.prototype, props, true ), X_Class_CommonMethods, false );\r
                        klass.prototype.constructor = klass;\r
                } else\r
                if( X_Class_use_proto_ ){\r
@@ -299,12 +355,13 @@ X.Class = {
                        if( X_Class_traits ){\r
                                klass.prototype.__proto__ = X_Class_traits;\r
                        } else {\r
-                               X_Class_override( klass.prototype, X_Class_CommonProps, false );\r
+                               X_Class_override( klass.prototype, X_Class_CommonMethods, false );\r
                        };\r
                } else {\r
-                       klass.prototype = X_Class_override( X_Class_override( X_Class_traits || klass.prototype, props, true ), X_Class_CommonProps, false );\r
+                       klass.prototype = X_Class_override( X_Class_override( X_Class_traits || klass.prototype, props, true ), X_Class_CommonMethods, false );\r
                        klass.prototype.constructor = klass;\r
                };\r
+               \r
                klass.name = displayName;\r
                \r
                if( opt_abstract ){\r
@@ -340,6 +397,8 @@ X.Class = {
        \r
 };\r
 \r
+\r
+\r
 // ------------------------------------------------------------------------- //\r
 // --- implements ---------------------------------------------------------- //\r
 // ------------------------------------------------------------------------- //\r
@@ -415,13 +474,19 @@ function X_Class_override( target, src, force ){
                        X.Logger.critical( p + ' is reserved!' );\r
                        return;\r
                };\r
-               if( force || target[ p ] === void 0 ){\r
+               if( force || target[ p ] === undefined ){\r
                        target[ p ] = src[ p ];\r
                };\r
        };\r
        return target;\r
 };\r
 \r
+/**\r
+ * スーパークラスか?調べます。\r
+ * @alias __ClassBase__.superClassOf\r
+ * @param klass {__ClassBase__}\r
+ * @return {boolean}\r
+ */\r
 function X_Class_superClassOf( klass ){\r
        var myDef      = X_Class_getClassDef( this ),\r
                targetDef  = X_Class_getClassDef( klass ),\r
@@ -436,13 +501,26 @@ function X_Class_superClassOf( klass ){
        return false;\r
 };\r
 \r
+/**\r
+ * サブクラスか?調べます。\r
+ * @alias __ClassBase__.subClassOf\r
+ * @type {Function}\r
+ * @param klass {__ClassBase__}\r
+ * @return {boolean}\r
+ */\r
 function X_Class_subClassOf( klass ){\r
-       return X_Class_superClassOf.call( klass, this );\r
+       return klass && X_Class_superClassOf.call( klass, this );\r
 };\r
-       \r
-/* サブクラスを作るメソッド  \r
- * var subClass = superClass.inherits( ... ) \r
- * http://d.hatena.ne.jp/m-hiyama/20051018/1129605002\r
+                       \r
+/**\r
+ * サブクラスを作ります。与える引数は X.Class.create と同じです。http://d.hatena.ne.jp/m-hiyama/20051018/1129605002\r
+ * @alias __ClassBase__.inherits\r
+ * @example var SubClass = SuperClass.inherits( 'Sub', X.Class.FINAL, { ... } );\r
+ * @param {string} [displayName] クラスの名前\r
+ * @param {number} [classSetting=0] X.Class.POOL_OBJECT | X.Class.FINAL など\r
+ * @param {__ClassBase__=} [privateClass] このクラスとペアで動作するシャドウクラス\r
+ * @param {object} [props={}] このクラスのメンバと関数。コンストラクタは Constructor と書くこと\r
+ * @return {__ClassBase__}\r
  */\r
 function X_Class_inherits( /* displayName, classSetting, opt_PrivateClass, props */ ){\r
        var args        = X_Object_cloneArray( arguments ),\r
@@ -472,7 +550,7 @@ function X_Class_inherits( /* displayName, classSetting, opt_PrivateClass, props
                classSetting = superDef.setting;// &= ~X.Class.ABSTRACT;\r
        };\r
        if( superDef.isPrivate ) classSetting = classSetting | X.Class.PRIVATE_DATA;\r
-       //opt_super = !!( classSetting & X.Class.SUPER_ACCESS );\r
+\r
        params.push( classSetting );\r
 \r
        // サブクラスのシャドウ\r