OSDN Git Service

Version 0.6.157, add X.Net.Form & fix X.EventDispatcher.
authoritozyun <itozyun@user.sourceforge.jp>
Sun, 7 Jun 2015 12:37:38 +0000 (21:37 +0900)
committeritozyun <itozyun@user.sourceforge.jp>
Sun, 7 Jun 2015 12:37:38 +0000 (21:37 +0900)
20 files changed:
0.6.x/js/01_core/04_XObject.js
0.6.x/js/01_core/05_XString.js
0.6.x/js/01_core/10_XCallback.js
0.6.x/js/01_core/16_XViewPort.js
0.6.x/js/05_util/01_XNinjaIframe.js
0.6.x/js/05_util/02_XJSON.js
0.6.x/js/06_net/00_XNet.js
0.6.x/js/06_net/02_XNetJSONP.js
0.6.x/js/06_net/03_XNetForm.js [new file with mode: 0644]
0.6.x/js/06_net/05_XXHRGadget.js
0.6.x/js/06_net/10_XOAuth2.js
0.6.x/js/07_audio/00_XAudio.js
0.6.x/js/20_ui/02_XUI_Attr.js
0.6.x/js/20_ui/04_XUI_Event.js
0.6.x/js/20_ui/06_AbstractUINode.js
0.6.x/js/20_ui/08_Box.js
0.6.x/js/20_ui/15_ScrollBox.js
0.6.x/js/20_ui/16_Repeater.js
0.6.x/js/20_ui/17_List.js
0.6.x/js/20_ui/17_Text.js

index 6d9941a..c12c3bd 100644 (file)
@@ -3,13 +3,12 @@
  * 但し for( name in object ) については構文解析エラーになる環境はありません。\r
  * @alias X.Object.inObject\r
  * @function\r
- * @param {string} name \r
+ * @param {string|number} name \r
  * @param {object} obj \r
  * @return {boolean} name が定義されている(値が undefined や null でも) -> true\r
  */\r
 var X_Object_inObject = X_UA[ 'IE' ] < 5.5 ? // TODO JScript で判定\r
-       (function( name, obj ){\r
-               var p;\r
+       (function( name, obj, p ){\r
                if( obj[ name ] ) return true; // quick\r
                name += ''; // 数値も許可\r
                for( p in obj ){\r
@@ -17,7 +16,7 @@ var X_Object_inObject = X_UA[ 'IE' ] < 5.5 ? // TODO JScript で判定
                };\r
                return false;\r
        }) :\r
-       new Function( 'a,b', 'return a in b' );// なぜか ie5 でもerror\r
+       new Function( 'a,b', 'return a in b' );\r
 \r
 \r
 // ------------------------------------------------------------------------- //\r
index b77d19f..c9a9b60 100644 (file)
@@ -88,7 +88,7 @@ function X_String_whiteSpaceToTag( text ){
 function X_String_chrReferanceTo( str ){\r
     if( str == null ) return '';\r
     return str.toString()\r
-       .split( '&quot;' ).join( '"' )\r
+       .split( '&quot;' ).join( '"' ) // first!\r
        .split( '&amp;' ).join( '&' )\r
        .split( '&lt;' ).join( '<' )\r
        .split( '&gt;' ).join( '>' )\r
@@ -97,9 +97,10 @@ function X_String_chrReferanceTo( str ){
 \r
 function X_String_toChrReferance( str ){\r
     if( str == null ) return '';\r
+    str += '';\r
     return str.toString()\r
-       .split( '"' ).join( '&quot;' )\r
        .split( '&' ).join( '&amp;' )\r
+       .split( '"' ).join( '&quot;' )\r
        .split( '<' ).join( '&lt;' )\r
        .split( '>' ).join( '&gt;' )\r
        .split( ' ' ).join( '&nbsp;' );\r
index e427160..9094791 100644 (file)
@@ -18,6 +18,8 @@ var
        X_Callback_HANDLEEVENT      = 2,\r
        /** @const */\r
        X_Callback_FUNC_ONLY        = 3,\r
+       /** @const */\r
+       X_Callback_THIS_FUNCNAME    = 4,\r
 \r
        /** @const */\r
        X_Callback_NONE             =  0,\r
@@ -177,6 +179,7 @@ function X_Callback_create( thisObject, opt_callback, opt_args /* [ listener ||
                _obj = ret( X_Closure_COMMAND_BACK );\r
                \r
                _obj.kind       = obj.kind;\r
+               _obj.name       = obj.name;\r
                _obj.func       = obj.func;\r
                _obj.context    = obj.context;\r
                _obj.supplement = obj.supplement;\r
@@ -193,12 +196,16 @@ function X_Callback_create( thisObject, opt_callback, opt_args /* [ listener ||
 function X_Callback_classifyCallbackArgs( arg1, arg2, arg3, alt_context ){\r
        var obj;\r
        \r
-       if( arg1 && X_Type_isFunction( arg2 ) ){\r
+       if( X_Type_isObject( arg1 ) && X_Type_isFunction( arg2 ) ){\r
                obj  = { context : arg1, func : arg2, kind : X_Callback_THIS_FUNC };\r
        } else\r
-       if( arg1 && X_Type_isFunction( arg1[ 'handleEvent' ] ) ){\r
-               obj  = { context : arg1, kind : X_Callback_HANDLEEVENT };\r
-               arg3 = arg2;\r
+       if( X_Type_isObject( arg1 ) ){\r
+               if( arg2 && X_Type_isString( arg2 ) ){\r
+                       obj  = { context : arg1, name : arg2, kind : X_Callback_THIS_FUNCNAME };\r
+               } else {\r
+                       obj  = { context : arg1, kind : X_Callback_HANDLEEVENT };\r
+                       arg3 = arg2;                    \r
+               };\r
        } else\r
        if( X_Type_isFunction( arg1 ) ){\r
                arg3 = arg2;\r
@@ -216,6 +223,10 @@ function X_Callback_classifyCallbackArgs( arg1, arg2, arg3, alt_context ){
                        obj  = { func : arg2, kind : X_Callback_FUNC_ONLY };\r
                };\r
        } else\r
+       if( alt_context && X_Type_isString( arg1 ) ){\r
+               arg3 = arg2;\r
+               obj  = { context : alt_context, name : arg1, kind : X_Callback_THIS_FUNCNAME };\r
+       } else\r
        if( alt_context ){\r
                obj  = { context : alt_context, kind : X_Callback_HANDLEEVENT };\r
                arg3 = arg1;\r
@@ -243,7 +254,7 @@ function X_Callback_proxyCallback( xfunc, _args ){
                thisObj = xfunc.context,\r
                func    = xfunc.func,\r
                supp    = xfunc.supplement,\r
-               temp, ret;      \r
+               temp, ret, funcName;    \r
        \r
        if( supp && supp.length ){\r
                temp = [];\r
@@ -263,9 +274,12 @@ function X_Callback_proxyCallback( xfunc, _args ){
 \r
                case X_Callback_THIS_FUNC :\r
                        return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );\r
-                       \r
+               \r
+               case X_Callback_THIS_FUNCNAME :\r
+                       funcName = xfunc.name;\r
                case X_Callback_HANDLEEVENT :\r
-                       temp = thisObj[ 'handleEvent' ];\r
+                       funcName = funcName || 'handleEvent';\r
+                       temp = thisObj[ funcName ];\r
                        if( X_Type_isFunction( temp ) ){\r
                                return args.length === 0 ? thisObj[ 'handleEvent' ]() :\r
                                           args.length === 1 ? thisObj[ 'handleEvent' ]( args[ 0 ] ) : temp.apply( thisObj, args );\r
@@ -298,6 +312,7 @@ function X_Callback_correct( f ){
                X_Callback_POOL_LIST[ X_Callback_POOL_LIST.length ] = f;\r
                obj = f( X_Closure_COMMAND_BACK );\r
                delete obj.kind;\r
+               if( obj.name ) delete obj.name;\r
                if( obj.func ) delete obj.func;\r
                if( obj.context ) delete obj.context;\r
                if( obj.supplement ) delete obj.supplement;\r
index a55a12e..0cc12dd 100644 (file)
@@ -311,7 +311,7 @@ X[ 'ViewPort' ] = {
         * @alias X.Doc.html
         * @type {Node}
         */
-                       X[ 'Doc' ][ 'html' ] = html = X_Node_html = elmHtml && new Node( elmHtml )[ 'removeClass' ]( 'js-disabled' )[ 'addClass' ]( X_UA_classNameForHTML );
+                       X[ 'Doc' ][ 'html' ] = html = X_Node_html = elmHtml && Node( elmHtml )[ 'removeClass' ]( 'js-disabled' )[ 'addClass' ]( X_UA_classNameForHTML );
                        html[ '_flags' ] |= X_NodeFlags_IN_TREE;
 
        /**
@@ -319,14 +319,14 @@ X[ 'ViewPort' ] = {
         * @alias X.Doc.head
         * @type {Node}
         */                     
-                       X[ 'Doc' ][ 'head' ] = head = X_Node_head = elmHead && new Node( elmHead );
+                       X[ 'Doc' ][ 'head' ] = head = X_Node_head = elmHead && Node( elmHead );
 
        /**
         * Node( documentElement )
         * @alias X.Doc.body
         * @type {Node}
         */             
-                       X[ 'Doc' ][ 'body' ] = body = X_Node_body = new Node( elmBody );
+                       X[ 'Doc' ][ 'body' ] = body = X_Node_body = Node( elmBody );
 
                        body[ 'parent ' ] = head[ 'parent' ] = html;
                        html[ '_xnodes' ] = [ head, body ];
index 9e3e810..8507c5e 100644 (file)
@@ -75,7 +75,11 @@ X[ 'Util' ][ 'NinjaIframe' ] = Node[ 'inherits' ](
                        if( !opt_contentHTML && opt_contentHTML !== '' ) return this;\r
                        \r
                        this._contentHTML = opt_contentHTML;\r
-                       X_UA[ 'IE' ] < 9 || X_Util_NinjaIframe_writeToIframe( this );\r
+\r
+                       if( !( X_UA[ 'IE' ] < 9 ) ){\r
+                               X_Util_NinjaIframe_writeToIframe( this );\r
+                               this._ready = true;\r
+                       };\r
                        \r
                        return this;\r
                },\r
@@ -138,7 +142,6 @@ function X_Util_NinjaIframe_writeToIframe( that ){
                html = that._contentHTML;\r
                \r
        delete that._contentHTML;\r
-       that._ready = true;\r
 \r
        idoc.open();\r
        idoc.writeln( html );\r
index e69de29..698927a 100644 (file)
@@ -0,0 +1,17 @@
+var X_JSON = X[ 'JSON' ] = window.JSON || {\r
+       'stringify' : X_JSON_stringify,\r
+       \r
+       'parse'     : X_String_parseTrustedJsonString\r
+};\r
+\r
+function X_JSON_stringify( obj ){\r
+       var json = '', k, v;\r
+       for( k in obj ){\r
+               if( json ) json += ',';\r
+               v = obj[ k ];\r
+               v = v || v === 0 ? v : null;\r
+               json += '"' + k + '":' + ( X_Type_isObject( v ) ? X_NET_GIMR_toJSONString( v ) : X_Type_isString( v ) ? '"' + v + '"' : v );\r
+       };\r
+       //console.log( json );\r
+       return '{' + json + '}';\r
+};
\ No newline at end of file
index cc402b0..55f0496 100644 (file)
@@ -60,6 +60,9 @@
  * // JSONP\r
  * var net = X.Net( { jsonp : urlString, staticCallbackName : callbackName, useXDomainWall : false } );\r
  * \r
+ * // Form\r
+ * var net = X.Net( { form : urlString, method : 'POST', target : '_self', params : {} } ); // _self, _parent, _top の場合、ページから離脱する\r
+ * \r
  * // Image preload & getSize\r
  * var net = X.Net( { image : src, sizeDetection : true } );\r
  * \r
@@ -77,23 +80,23 @@ X[ 'Net' ] = X_EventDispatcher[ 'inherits' ](
                                var v, opt, url, type, auth;\r
                                \r
                                if( X_Type_isObject( opt = urlOrObject ) ){\r
-                                       if( v = opt[ 'xhr' ] ){\r
+                                       if( X_Type_isString( v = opt[ 'xhr' ] ) ){\r
                                                url  = v;\r
                                                type = X_NET_TYPE_XHR;\r
                                        } else\r
-                                       if( v = opt[ 'jsonp' ] ){\r
+                                       if( X_Type_isString( v = opt[ 'jsonp' ] ) ){\r
                                                url  = v;\r
                                                type = X_NET_TYPE_JSONP;\r
                                        } else\r
-                                       if( v = opt[ 'img' ] || opt[ 'image' ] ){\r
+                                       if( X_Type_isString( v = opt[ 'img' ] || opt[ 'image' ] ) ){\r
                                                url  = v;\r
                                                type = X_NET_TYPE_IMAGE;\r
                                        } else\r
-                                       if( v = opt[ 'form' ] ){\r
+                                       if( X_Type_isString( v = opt[ 'form' ] ) ){\r
                                                url  = v;\r
                                                type = X_NET_TYPE_FORM;\r
                                        } else\r
-                                       if( v = opt[ 'type' ] ){\r
+                                       if( X_Type_isString( v = opt[ 'type' ] ) ){\r
 \r
                                                switch( v ){\r
                                                        case 'xhr' :\r
@@ -113,7 +116,7 @@ X[ 'Net' ] = X_EventDispatcher[ 'inherits' ](
                                                                alert( 'X.Net args error' );\r
                                                                return; \r
                                                };\r
-                                               url = opt[ 'url'  ];\r
+                                               url = opt[ 'url' ];\r
                                        };\r
                                        \r
                                        if( !X_Type_isString( url ) ){\r
@@ -317,7 +320,7 @@ function X_NET_shiftQueue(){
                        X_NET_currentWrapper = X_NET_JSONPWrapper || X_TEMP.X_NET_JSONP_init();\r
                        break;\r
                case X_NET_TYPE_FORM :\r
-                       X_NET_currentWrapper = X_NET_FormWrapper;\r
+                       X_NET_currentWrapper = X_NET_FormWrapper  || X_TEMP.X_NET_Form_init();\r
                        break;\r
                case X_NET_TYPE_IMAGE :\r
                        X_NET_currentWrapper = X_NET_ImageWrapper || X_TEMP.X_NET_Image_init();\r
index 43732b4..7b1c4da 100644 (file)
@@ -50,12 +50,15 @@ var X_NET_JSONP_ACCESS_KEY = Math.random(),
        X_Net_JSONP_errorTimerID;
 
 X_TEMP.X_NET_JSONP_init = function(){
+       X_NET_JSONPWrapper = X_Class_override( X[ 'Util' ][ 'NinjaIframe' ](), X_TEMP.X_NET_JSONP_params );
        
        delete X_TEMP.X_NET_JSONP_init;
+       delete X_TEMP.X_NET_JSONP_params;
        
-       return X_NET_JSONPWrapper = X_Class_override(
-               X[ 'Util' ][ 'NinjaIframe' ](),
-               {
+       return X_NET_JSONPWrapper;
+};
+
+X_TEMP.X_NET_JSONP_params = {
        
                        _busy         : false,
                        _canceled     : false,
@@ -187,14 +190,12 @@ X_TEMP.X_NET_JSONP_init = function(){
                        
                        reset : function(){
                                X_NET_JSONPWrapper._busy = X_NET_JSONPWrapper._canceled = false;
-                               X_Net_JSONP_onloadCount = 0;
                                X_NET_JSONPWrapper[ 'unlisten' ]( [ 'ninjaload', 'ninjaerror' ], X_NET_JSONP_iframeListener );
                                X_NET_JSONPWrapper[ 'refresh' ]( '' );
                                X_Net_JSONP_errorTimerID && X_Timer_remove( X_Net_JSONP_errorTimerID );
+                               X_Net_JSONP_errorTimerID = X_Net_JSONP_onloadCount = 0;
                        }
-               }
-       );
-};
+               };
 
 function X_NET_JSONP_iframeListener( e ){
        switch( e.type ){
diff --git a/0.6.x/js/06_net/03_XNetForm.js b/0.6.x/js/06_net/03_XNetForm.js
new file mode 100644 (file)
index 0000000..1dec5db
--- /dev/null
@@ -0,0 +1,102 @@
+X[ 'Net' ][ 'Form' ] = {\r
+       // 隠し iframe 使用の可否\r
+};\r
+\r
+var X_NET_Form_errorTimerID, X_Net_Form_onloadCount = 0;\r
+\r
+X_TEMP.X_NET_Form_init = function(){\r
+       X_NET_FormWrapper = X_Class_override( X[ 'Util' ][ 'NinjaIframe' ](), X_TEMP.X_NET_Form_params );\r
+       \r
+       delete X_TEMP.X_NET_Form_init;\r
+       delete X_TEMP.X_NET_Form_params;\r
+       \r
+       return X_NET_FormWrapper;\r
+};\r
+\r
+/*\r
+ * form 構築時に "><script> といった文字列の挿入を禁止するために " を エスケープする、併せて改行文字を消す\r
+ */\r
+function X_NET_Form_escapeQuote( str ){\r
+       return X_String_toChrReferance( str );\r
+};\r
+\r
+X_TEMP.X_NET_Form_params = {\r
+       \r
+                       _busy     : false,\r
+                       _canceled : false,\r
+                       \r
+                       timeout   : 1000,\r
+                       isJump    : false, // ページを離脱するか?\r
+                       \r
+                       load : function( option ){\r
+                               //createURL\r
+                               var params  = option[ 'params' ] || {},\r
+                                       target  = option[ 'target' ],\r
+                                       html, k;\r
+                                       \r
+                               target = target === '_self' ? '_parent' : target === '_blank' ? '_self' : target,\r
+                               html   = [\r
+                                       '<form method="', X_NET_Form_escapeQuote( option[ 'method' ] || 'GET' ), \r
+                                               '" action="', X_NET_Form_escapeQuote( option[ 'url' ] || '' ), \r
+                                               '" target="', X_NET_Form_escapeQuote( target || '_self' ),\r
+                                               '">' ],\r
+                               k;\r
+                               \r
+                               if( target === '_top' || target === '_parent' ) this.isJump = true;\r
+                               if( 0 <= option[ 'timeout' ] ) this.timeout = option[ 'timeout' ];\r
+                               \r
+                               for( k in params ){\r
+                                       // TODO 使用すべきでない name\r
+                                       html.push( '<input type="hidden" name="', X_NET_Form_escapeQuote( k ), '" value="', X_NET_Form_escapeQuote( params[ k ] || '' ), '">' );\r
+                               };\r
+                               \r
+                               html.push( '</form><script>document.forms[0].submit();</script>' );\r
+                               \r
+                               X_NET_FormWrapper\r
+                                       [ 'refresh' ]( html.join( '' ) )\r
+                                       [ 'listen' ]( [ 'ninjaload', 'ninjaerror' ], X_NET_Form_iframeListener );\r
+                                                       \r
+                               X_NET_FormWrapper._busy = true;\r
+                       },\r
+                       \r
+                       cancel : function(){\r
+                               X_NET_FormWrapper.reset();\r
+                               X_NET_FormWrapper._canceled = true;\r
+                       },\r
+                       \r
+                       reset : function(){\r
+                               X_NET_FormWrapper._busy = X_NET_FormWrapper._canceled = false;\r
+                               X_NET_FormWrapper[ 'unlisten' ]( [ 'ninjaload', 'ninjaerror' ], X_NET_Form_iframeListener );\r
+                               X_NET_FormWrapper[ 'refresh' ]( '' );\r
+                               X_NET_Form_errorTimerID && X_Timer_remove( X_NET_Form_errorTimerID );\r
+                               X_NET_Form_errorTimerID = X_Net_Form_onloadCount = 0;\r
+                       }\r
+               };\r
+\r
+function X_NET_Form_iframeListener( e ){\r
+       var idoc;\r
+       \r
+       switch( e.type ){\r
+               case 'ninjaload' :\r
+                       if( this.isJump ){\r
+                               return;\r
+                       };\r
+                       \r
+                       if( ++X_Net_Form_onloadCount === 1 ){\r
+                               X_NET_Form_errorTimerID = X_NET_FormWrapper[ 'asyncDispatch' ]( this.timeout, X_EVENT_ERROR );\r
+\r
+                               // TODO レスポンスの html にアクセスしたい場合\r
+                               // TODO samedomain or xiframe-sender\r
+                               \r
+                               idoc = this[ '_rawObject' ].contentDocument || this._iwin.document,\r
+                               \r
+                               X_NET_FormWrapper[ 'asyncDispatch' ]( { type : X_EVENT_SUCCESS, responce : idoc && idoc.body ? idoc.body.innerHTML : '' } );\r
+                       };\r
+                       break;\r
+               case 'ninjaerror' :\r
+                       console.log( 'iframe onerror' );\r
+                       X_NET_FormWrapper[ 'asyncDispatch' ]( X_EVENT_ERROR );\r
+                       break;\r
+       };\r
+       return X_Callback_UN_LISTEN;\r
+};\r
index 905e098..1d294e0 100644 (file)
@@ -245,4 +245,3 @@ X_TEMP.X_Net_GIMR_props = {
                }\r
        };\r
 \r
-\r
index 2d5150f..ab34837 100644 (file)
@@ -58,7 +58,7 @@ X[ 'OAuth2' ] = X_EventDispatcher[ 'inherits' ](
                                obj.updateRequest = X_NET_OAUTH2_updateRequest;                         
                                
                                if( _getAccessToken( this ) && ( expires_at = _getAccessTokenExpiry( this ) ) ){
-                                       if( expires_at < X_Timer_now() + 300000 ){ // 寿命が5分を切った
+                                       if( expires_at < X_Timer_now() + ( obj[ 'refreshMargin' ] || 300000 ) ){ // 寿命が5分を切った
                                                this[ 'refreshToken' ]();
                                        } else {
                                                obj.oauth2State = 4;
@@ -68,8 +68,8 @@ X[ 'OAuth2' ] = X_EventDispatcher[ 'inherits' ](
                                        this[ 'asyncDispatch' ]( X_EVENT_NEED_AUTH );
                                };
                                
-                               // TODO canUse
-                               // TODO kill の cancel
+                               // TODO canUse gadgetProxy
+                               this[ 'listen' ]( [ X_EVENT_KILL_INSTANCE, X_EVENT_SUCCESS, X_EVENT_ERROR, X_EVENT_NEED_AUTH ], X_NET_OAUTH2_handleEvent );
                        },
 
                        /**
@@ -137,6 +137,10 @@ X[ 'OAuth2' ] = X_EventDispatcher[ 'inherits' ](
                                        delete pair.net;
                                };
                                
+                               if( pair.oauth2State !== 1 ){
+                                       return;
+                               };
+                               
                                // http://kojikoji75.hatenablog.com/entry/2013/12/15/223839
                                X_NET_OAUTH2_authorizationWindow && X_NET_OAUTH2_authorizationWindow.open( 'about:blank', '_self' ).close();
                                X_NET_OAUTH2_authorizationWindow  = null;
@@ -151,12 +155,15 @@ X[ 'OAuth2' ] = X_EventDispatcher[ 'inherits' ](
                         * アクセストークンのリフレッシュ。
                         */
                        'refreshToken' : function(){
-                               // TODO 自動リフレッシュ
-
                                var pair = X_Pair_get( this );
                                
                                if( pair.net ) return;
                                
+                               if( pair.refreshTimerID ){
+                                       X_Timer_remove( pair.refreshTimerID );
+                                       delete pair.refreshTimerID;
+                               };
+                               
                                pair.oauth2State = 3;
                                
                                pair.net = X.Net( {
@@ -180,6 +187,27 @@ X[ 'OAuth2' ] = X_EventDispatcher[ 'inherits' ](
                }
        );
 
+function X_NET_OAUTH2_handleEvent( e ){
+       var pair = X_Pair_get( this );
+       
+       switch( e.type ){
+               case X_EVENT_KILL_INSTANCE :
+                       this[ 'cancelAuth' ]();
+               
+               case X_EVENT_ERROR :
+               case X_EVENT_NEED_AUTH :
+                       pair.refreshTimerID && X_Timer_remove( pair.refreshTimerID );
+                       break;
+                       
+               case X_EVENT_SUCCESS :
+                       pair.refreshTimerID && X_Timer_remove( pair.refreshTimerID );
+                       if( _getRefreshToken( this ) ){
+                               // 自動リフレッシュ
+                               pair.refreshTimerID = X_Timer_once( _getAccessTokenExpiry( this ) - X_Timer_now() - pair[ 'refreshMargin' ], this, this[ 'refreshToken' ] );
+                       };
+       };
+};
+
 function X_Net_OAuth2_detectAuthPopup(){
        var closed, search, pair = X_Pair_get( this );
        
index 1e6d9e5..017f79e 100644 (file)
@@ -163,6 +163,9 @@ X[ 'Audio' ] = X_EventDispatcher[ 'inherits' ](
        }\r
 );\r
 \r
+// TODO\r
+X[ 'Audio' ][ 'canPlay' ] = {};\r
+\r
 function X_Audio_handleEvent( e ){\r
        var backend;\r
        \r
index 5a0bd47..2e865f3 100644 (file)
@@ -46,7 +46,7 @@ var XUI_Attr_AUTO = 1/0,//Number.POSITIVE_INFINITY,
                textShadowAlpha : true\r
        },\r
        XUI_Attr_Rename = {\r
-               bgColor       : 'background-color',\r
+               bgColor       : 'backgroundColor',\r
                fontColor     : 'color',\r
                fontBold      : 'fontWeight',\r
                fontItalic    : 'fontStyle',\r
@@ -62,12 +62,12 @@ var XUI_Attr_AUTO = 1/0,//Number.POSITIVE_INFINITY,
  */\r
        XUI_Attr_Support = XUI_Attr_createAttrDef( 0,\r
 {\r
-       className         : [ null,           XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.DEFAULT_ONLY | XUI_Attr_Type.STRING ],\r
-       pointerHoverClass : [ null,           XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.DEFAULT_ONLY | XUI_Attr_Type.STRING ],\r
+       className         : [ '',             XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.DEFAULT_ONLY | XUI_Attr_Type.STRING ],\r
+       pointerHoverClass : [ '',             XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.DEFAULT_ONLY | XUI_Attr_Type.STRING ],\r
        pointerDownClass  : [ null,           XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.DEFAULT_ONLY | XUI_Attr_Type.STRING ],\r
        invalidLayoutColor: [ null,           XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.DEFAULT_ONLY | XUI_Attr_Type.COLOR ],\r
        \r
-       dataFeild         : [ null,           XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.DEFAULT_ONLY | XUI_Attr_Type.STRING ],\r
+       dataFeild         : [ '',             XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.INIT_ONLY | XUI_Attr_Type.STRING ],\r
        \r
        role              : [ 1,              XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.INIT_ONLY | XUI_Attr_Type.LIST, 'none,chrome' ],\r
        selectable        : [ false,          XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.INIT_ONLY | XUI_Attr_Type.BOOLEAN ],\r
@@ -76,17 +76,17 @@ var XUI_Attr_AUTO = 1/0,//Number.POSITIVE_INFINITY,
        pointerEnabled    : [ false,          XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.BOOLEAN ],\r
        pointerChildren   : [ true,           XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.BOOLEAN ],\r
        cursor            : [ 1,              XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.LIST, XUI_Attr_Option.CURSOR ],\r
-       tooltip           : [ null,           XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.STRING ],\r
+       tooltip           : [ '',           XUI_Dirty.CLEAN,  XUI_Attr_USER.UINODE, XUI_Attr_Type.STRING ],\r
        \r
        borderWidth       : [ 0,              XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.QUARTET | XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT  ], // em [ top, right, bottom, left ]\r
        padding           : [ 0,              XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.QUARTET | XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT ],\r
        \r
-       width             : [ XUI_Attr_AUTO, XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT | XUI_Attr_Type.AUTO ],\r
+       width             : [ XUI_Attr_AUTO,  XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT | XUI_Attr_Type.AUTO ],\r
        minWidth          : [ 0,              XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT ],\r
-       maxWidth          : [ XUI_Attr_AUTO, XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT | XUI_Attr_Type.AUTO ],\r
-       height            : [ XUI_Attr_AUTO, XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT | XUI_Attr_Type.AUTO ],\r
+       maxWidth          : [ XUI_Attr_AUTO,  XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT | XUI_Attr_Type.AUTO ],\r
+       height            : [ XUI_Attr_AUTO,  XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT | XUI_Attr_Type.AUTO ],\r
        minHeight         : [ 0,              XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT ],\r
-       maxHeight         : [ XUI_Attr_AUTO, XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT | XUI_Attr_Type.AUTO ],\r
+       maxHeight         : [ XUI_Attr_AUTO,  XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT | XUI_Attr_Type.AUTO ],\r
        sizing            : [ 1,              XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LIST, XUI_Attr_Option.BOX_SIZING ],\r
        left              : [ null,           XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT | XUI_Attr_Type.MINUS_LENGTH | XUI_Attr_Type.MINUS_PERCENT ],\r
        top               : [ null,           XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT | XUI_Attr_Type.MINUS_LENGTH | XUI_Attr_Type.MINUS_PERCENT ],\r
index 97ddb1f..bea9f04 100644 (file)
@@ -111,9 +111,11 @@ var XUI_Event = X[ 'UI' ][ 'Event' ] = {
        PAGE_AFTER_HIDE     : ++X_Event_last,\r
 \r
        // X.UI.Form\r
-       CHANGE            : ++X_Event_last,\r
-       SUBMIT            : ++X_Event_last,\r
-       SELECT            : ++X_Event_last, // click or tap or enterkey\r
+       CHANGE              : ++X_Event_last,\r
+       SUBMIT              : ++X_Event_last,\r
+       SELECT              : ++X_Event_last, // click or tap or enterkey\r
+       \r
+       ITEMDATA_CHANGED    : ++X_Event_last,\r
        \r
        IdToName : {},\r
        NameToID : {}\r
index 4ca1595..87cea63 100644 (file)
@@ -3,6 +3,8 @@ var XUI_AbstractUINode = X_EventDispatcher[ 'inherits' ](
        'X.UI._AbstractUINode',\r
        X_Class.ABSTRACT,\r
        {\r
+               itemData          : null,\r
+               \r
                phase             : 0,\r
                dirty             : XUI_Dirty.CLEAN,\r
                \r
@@ -77,8 +79,21 @@ var XUI_AbstractUINode = X_EventDispatcher[ 'inherits' ](
                },\r
                \r
                addToParent : function( xnodeParent ){\r
+                       var attr = this.attrObject || this.attrClass.prototype,\r
+                               usableAttrs = this.usableAttrs,\r
+                               i = 0, l = usableAttrs.length, def;\r
+                       \r
                        xnodeParent && xnodeParent[ 'append' ]( this.xnode );\r
                        \r
+                       if( attr ){\r
+                               for( k in usableAttrs ){\r
+                                       def = usableAttrs[ k ];\r
+                                       if( def[ 2 ] === XUI_Attr_USER.XNODE && X_Object_inObject( def.No, attr ) && attr[ k ] !== def[ 0 ] ){\r
+                                               this.xnode[ 'css' ]( XUI_Attr_Rename[ k ] || k, XUI_AbstractUINode_createCssText( this, k ) );\r
+                                       };\r
+                               };\r
+                       };\r
+                       \r
                        this.phase = 2;\r
                        this[ 'dispatch' ]( XUI_Event.ADDED );\r
                },\r
@@ -91,6 +106,7 @@ var XUI_AbstractUINode = X_EventDispatcher[ 'inherits' ](
                        this.User[ 'dispatch' ]( XUI_Event.CREATION_COMPLETE );\r
                        \r
                        // html 要素が親に追加されるまで控えていたイベントの登録\r
+                       // TODO listenOnce\r
                        if( events && ( l = events.length ) ){\r
                                for( i = 0; i < l; ++i ){\r
                                        this.listen.apply( this, events[ i ] );\r
@@ -229,6 +245,7 @@ var XUI_AbstractUINode = X_EventDispatcher[ 'inherits' ](
 \r
                        if( !v && v !== 0 ) v = defaultVal;\r
                        \r
+                       // UIAttrClass の初期設定の場合、ここで終わる\r
                        if( XUI_attrClassProto ){\r
                                attrs[ propID ] = v;\r
                                return;                 \r
@@ -786,8 +803,15 @@ var XUI_AbstractUINode = X_EventDispatcher[ 'inherits' ](
                        return ret;\r
                },\r
                \r
-               setItemData : function(){\r
-                       // this[ 'dispatch' ]( UI_Event.ITEMDATA_CHANGED );\r
+               setItemData : function( itemData ){\r
+                       if( this.itemData === itemData ) return;\r
+\r
+                       this.itemData = itemData;\r
+\r
+                       this[ 'dispatch' ]( { type : XUI_Event.ITEMDATA_CHANGED, itemData : itemData } );\r
+                       // itemData && itemData.listen( X_Event_CHANGED )\r
+                       // dataFeild dataFormatter dataValidator\r
+                       \r
                        // itemData.listen( X_Event_CHANGED ) -> this[ 'dispatch' ]( UI_Event.ITEMDATA_UPDATED );\r
                }\r
                \r
@@ -926,11 +950,11 @@ X.UI.AbstractUINode = X_Class_create(
                                        };\r
                                };\r
                        } else\r
-                       if( X_Type_isString( nameOrObject ) ){\r
+                       if( X_Type_isString( nameOrObject ) && ( def = p.usableAttrs[ nameOrObject ] ) ){\r
                                if( valueOrUnit !== undefined ){\r
                                        if( 'em,%'.indexOf( valueOrUnit ) === -1 ){\r
                                                // setter\r
-                                               p.setAttr( nameOrObject, valueOrUnit );\r
+                                               p.setAttr( nameOrObject, def, valueOrUnit );\r
                                        } else {\r
                                                // getter with unit\r
                                                return p.getAttrWithUnit( nameOrObject, valueOrUnit );\r
@@ -1011,11 +1035,21 @@ X.UI.AbstractUINode = X_Class_create(
                 * Repeater に於いて、繰り返されるアイテムの元(itemRenderer)からの複製に使用\r
                 */\r
                clone : function( opt_cloneListener ){\r
-                       var newNode = this.constructor(),\r
-                               newPair = X_Pair_get( newNode ),\r
+                       var newNode,\r
+                               //newPair = X_Pair_get( newNode ),\r
                                pair    = X_Pair_get( this ),\r
                                attr, listeners, type, list, i, l;\r
 \r
+                       // attr もコピー\r
+                       if( pair.attrObject ){\r
+                               attr = {};\r
+                               for( k in pair.usableAttrs ){\r
+                                       def = pair.usableAttrs[ k ];\r
+                                       attr[ k ] = pair.attrObject[ def.No ];\r
+                               };\r
+                               newNode = this.constructor( attr );\r
+                       };\r
+\r
                        // handleEvent 等の拡張されたオブジェクトもコピーする!\r
                        for( k in this ){\r
                                if( this[ k ] !== newNode[ k ] && !newNode[ k ] ) newNode[ k ] = this[ k ];\r
@@ -1023,17 +1057,14 @@ X.UI.AbstractUINode = X_Class_create(
                        \r
                        // User.UINODE な値は pair にコピーされているのでこれをコピー\r
                        for( k in pair ){\r
-                               if( pair[ k ] !== newPair[ k ] && !newPair[ k ] ) newPair[ k ] = pair[ k ];\r
+                               //pair[ k ] !== newPair[ k ] && !newPair[ k ] && console.log( k );\r
+                               //if( pair[ k ] !== newPair[ k ] && !newPair[ k ] && k !== 'attrObject' && k !== '_listeners' ){\r
+                                       //newPair[ k ] = pair[ k ];\r
+                                       //console.log( k );\r
+                               //};\r
                        };\r
                        \r
-                       // attr もコピー\r
-                       if( pair.attrObject ){\r
-                               attr = pair.attrClass();\r
-                               for( k in pair.attrObject ){\r
-                                       if( pair.attrObject[ k ] !== attr[ k ] ) attr[ k ] = pair.attrObject[ k ];\r
-                               };\r
-                               newPair.attrObject = attr;\r
-                       };\r
+\r
                        \r
                        // listener もコピーする!\r
                        if( opt_cloneListener && ( listeners = pair[ '_listeners' ] ) ){\r
@@ -1070,6 +1101,12 @@ X.UI.AbstractUINode = X_Class_create(
                                                };\r
                                        };                              \r
                                };\r
+                       } else\r
+                       if( opt_cloneListener && ( list = this.reserveEvents ) ){\r
+                               for( i = 0, l = list.length; i < l; ++i ){\r
+                                       f = list[ i ];\r
+                                       newNode[ f.once ? 'listenOnce' : 'listen' ]( f[ 0 ], newNode, f[ 1 ], f[ 2 ] );\r
+                               };      \r
                        };\r
                        \r
                        return newNode;\r
index 3fb51e4..a030267 100644 (file)
@@ -124,10 +124,6 @@ var XUI_Box = XUI_AbstractUINode.inherits(
                initialize : function( root, rootData, parent, parentData ){\r
                        var uinodes = this.uinodes,\r
                                i       = uinodes && uinodes.length;\r
-                       this.root       = root;\r
-                       this.rootData   = rootData;\r
-                       this.parent     = parent;\r
-                       this.parentData = parentData;\r
                        \r
                        if( i ){\r
                                for( ; i; ){\r
@@ -135,8 +131,7 @@ var XUI_Box = XUI_AbstractUINode.inherits(
                                };                              \r
                        };\r
                        \r
-                       this.phase = 1;\r
-                       this.User[ 'dispatch' ]( { type : XUI_Event.INIT } );\r
+                       XUI_AbstractUINode.prototype.initialize.apply( this, arguments );\r
                },\r
                \r
                addToParent : function( parentXNode ){\r
@@ -144,16 +139,13 @@ var XUI_Box = XUI_AbstractUINode.inherits(
                                l       = uinodes && uinodes.length,\r
                                i;\r
 \r
-                       parentXNode && parentXNode[ 'append' ]( this.xnode );\r
-                       \r
                        if( l ){\r
                                for( i = 0; i < l; ++i ){\r
                                        uinodes[ i ].addToParent( this.xnode );\r
                                };\r
                        };\r
                        \r
-                       this.phase = 2;\r
-                       this.User[ 'dispatch' ]( { type : XUI_Event.ADDED } );\r
+                       XUI_AbstractUINode.prototype.addToParent.apply( this, arguments );\r
                },\r
                \r
        /* Rellay */\r
@@ -216,7 +208,7 @@ var XUI_Box = XUI_AbstractUINode.inherits(
                \r
                addAt : function( index, _uinodes ){\r
                        //console.log( '# AddAt ' + this.phase )\r
-                       var uinodes = this.uinodes,\r
+                       var uinodes = this.uinodes || ( this.uinodes = [] ),\r
                                num     = uinodes.length,\r
                                p1      = 1 <= this.phase,\r
                                p2      = 2 <= this.phase,\r
index 47915ff..170dfe4 100644 (file)
@@ -40,7 +40,6 @@ var XUI_ScrollBox = XUI_ChromeBox.inherits(
                directionLocked : '',\r
                startTime       : 0,\r
                endTime         : 0,\r
-               isAnimating     : false,\r
                isInTransition  : false,\r
 \r
                hasHScroll      : false,\r
@@ -244,9 +243,10 @@ function X_UI_ScrollBox_onStart( e ){
        this.startTime       = X_Timer_now();\r
 \r
        // スクロール中の停止\r
-       if( this.isInTransition || this.isAnimating ){\r
-               this.isInTransition = this.isAnimating = false;\r
+       if( this.isInTransition ){\r
+               this.isInTransition = false;\r
                this[ 'dispatch' ]( XUI_Event.SCROLL_END );\r
+               // TODO current位置\r
                this.xnodeSlider.stop();\r
        };                      \r
 \r
@@ -272,7 +272,7 @@ function X_UI_ScrollBox_onMove( e ){
                absDistX, absDistY;\r
        // 規定以上の move でスクロール開始\r
 \r
-console.log( 'scrollmove ' + e.buttons + ' ' + e.button );\r
+//console.log( 'scrollmove ' + e.buttons + ' ' + e.button );\r
 \r
        if( !this.scrollEnabled || e.pointerType !== this.initiated ){\r
                return ret;\r
@@ -463,8 +463,8 @@ function X_UI_ScrollBox_resetPosition( that, time ){
                return false;\r
        };\r
 \r
-       //console.log( 'バウンド!' );\r
-       //console.log( 'rese x:' + x + ' y:' + y );\r
+       console.log( ' ===> resetPosition - バウンド!' );\r
+       console.log( '      x:' + x + ' y:' + y );\r
        that.scrollTo( x, y, time, that.bounceEasing, 1000 );\r
 \r
        return true;\r
@@ -509,7 +509,6 @@ function X_UI_ScrollBox_momentum( current, start, time, lowerMargin, wrapperSize
        };\r
 };\r
 \r
-// TODO Box の継承に!\r
 X.UI.ScrollBox = X.UI.ChromeBox.inherits(\r
        'ScrollBox',\r
        X_Class.NONE,\r
@@ -520,7 +519,7 @@ X.UI.ScrollBox = X.UI.ChromeBox.inherits(
                        if( XUI_ScrollBox.prototype.usableAttrs === XUI_ChromeBox.prototype.usableAttrs ){\r
                                XUI_ScrollBox.prototype.usableAttrs = supports = XUI_Attr_createAttrDef( XUI_Attr_Support, X_UI_ScrollBox_SUPPORT_ATTRS );\r
                \r
-                               XUI_ScrollBox.prototype.attrClass    = XUI_Attr_preset( XUI_Box.prototype.attrClass, supports, { width  : '100%', height : '100%', bgColor : 0x111111 } );\r
+                               XUI_ScrollBox.prototype.attrClass   = XUI_Attr_preset( XUI_Box.prototype.attrClass, supports, { width  : '100%', height : '100%', bgColor : 0x111111 } );\r
                        };\r
                        \r
                        var args = [\r
@@ -580,4 +579,5 @@ X.UI.ScrollBox = X.UI.ChromeBox.inherits(
                        \r
                }\r
        }\r
-);
\ No newline at end of file
+);\r
+\r
index 3f980f8..e709360 100644 (file)
@@ -13,16 +13,28 @@ var XUI_Repeater = XUI_Box.inherits(
                \r
                itemRenderer     : null,\r
                \r
+               itemNodes        : null,\r
                \r
                startIndex       : 0,\r
                startRenderIndex : 0,\r
                numItemsParPage  : 0,\r
+               numItemsPrev     : 0,\r
                numItems         : 0,\r
+               itemHeightLast   : 0,\r
+               itemHeightLastEM : 0,\r
                \r
                Constructor : function( user, dataSource, itemRenderer, attr ){\r
                        this.Super( user, null, [ attr ] );\r
                        this.dataSource   = dataSource;\r
                        this.itemRenderer = itemRenderer;\r
+                       this.itemNodes    = [];\r
+                       this.__item__     = X_Pair_get( itemRenderer );\r
+               },\r
+               \r
+               initialize : function(){\r
+                       XUI_AbstractUINode.prototype.initialize.apply( this, arguments );\r
+                       \r
+                       this.parent[ 'listen' ]( XUI_Event.SCROLL_END, this );\r
                },\r
                \r
                /*\r
@@ -55,56 +67,77 @@ var XUI_Repeater = XUI_Box.inherits(
                },\r
                \r
                handleEvent : function( e ){\r
-                       var scrollBox, scrollY, dataSource, offsetY, startIndex, maxIndex, offset, uinodes;\r
+                       var scrollBox, scrollY, dataSource, offsetY, startIndex, maxIndex, offset, itemNodes, ary, i, l;\r
                        \r
                        switch( e.type ){\r
                                case XUI_Event.SCROLL_END :\r
                                        scrollBox  = this.parentData;\r
-                                       scrollY    = scrollBox.scrollY;\r
+                                       scrollY    = scrollBox.scrollY;\r
                                        dataSource = this[ 'dataSource' ];\r
-                                       uinodes    = this.uinodes;\r
+                                       itemNodes  = this.itemNodes;\r
+                                       itemH      = this.itemHeightLast;\r
+                                       \r
                                        // transition Y を 0 付近に。\r
-                                       offsetY    = scrollY % this.itemHeightLast;\r
-                                       scrollBox.scrollTo( 0, offsetY, 0, '', 0 ); // anime無し\r
+                               \r
+                                       \r
                                        // startIndex の計算\r
-                                       startIndex = scrollY / this.itemHeightLast | 0;\r
-                                       maxIndex   = dataSource.length <= this.numItems ? 0 : dataSource.length - this.numItems;\r
+                                       startIndex = scrollY / itemH | 0;\r
+                                       \r
+                                       /*maxIndex   = dataSource.length <= this.numItems ? 0 : dataSource.length - this.numItems;\r
+                                       console.log( ' >>> ' + startIndex + ' ' + maxIndex );\r
+                                       \r
                                        startIndex =\r
                                                startIndex < 0 ? 0 :\r
-                                               maxIndex < startIndex ? maxIndex : startIndex;\r
+                                               maxIndex < startIndex ? maxIndex : startIndex; */\r
                                        // アイテムの座標の修正とレンジ外のアイテムを配列内で再配置\r
                                        offset = startIndex - this.startIndex; // visible な stratIndex renderStartIndex\r
+                                       this.startIndex = startIndex;\r
+                                       \r
+                                       console.log(  this.numItemsPrev + ' oo ' + offset )\r
                                        \r
                                        if( 0 < offset ){\r
-                                               this.addAt( last, uinodes.splice( 0, offset ) );\r
+                                               itemNodes.push.apply( itemNodes, itemNodes.splice( 0, offset ) );\r
                                        } else\r
-                                       if( offset < 0 ){\r
-                                               this.addAt( 0, uinodes.splice( uinodes.length - offset ) );\r
+                                       if( offset < 0 ){\r
+                                               itemNodes.unshift.apply( itemNodes, itemNodes.splice( itemNodes.length + offset ) );\r
                                        };\r
+\r
                                        // 再配置されたアイテムにitemData のセット\r
                                        this.updateItemRenderer( this.contentWidth, this.scrollPortHeight );\r
+                                       \r
+                                       \r
+                                       \r
+                                       offsetY  = scrollY % itemH;\r
+                                       offsetY  = offsetY === 0 ? 0 : ( offsetY - itemH );\r
+                                       offsetY += ( this.startRenderIndex - this.startIndex ) * itemH;\r
+                                       //console.log( ' ====> ' + this.startRenderIndex + ' -> ' + this.startIndex + ' scrollY:' + offsetY );\r
+\r
+                                       //scrollBox.scrollTo( 0, - scrollY, 0, '', 0 ); // anime無し                                                  \r
+                                       //console.log( '  <==== ' );\r
                                        break;\r
                        };\r
                },\r
                \r
                updateItemRenderer : function( _w, _h ){\r
-                       var uinodes    = this.uinodes || ( this.uinodes = [] ),\r
+                       var itemNodes  = this.itemNodes,\r
                                attrs      = this.attrObject || this.attrClass.prototype,\r
                                gapY       = XUI_AbstractUINode_calcValue( attrs[ this.usableAttrs.gapY.No ], _w ),\r
                                dataSource = this[ 'dataSource' ],\r
                                render     = this[ 'itemRenderer' ],\r
                                l          = dataSource.length,\r
-                               start      = this.startIndex - ( this.numItems - this.numItemsParPage ) / 2 | 0,\r
-                               itemH      = this.itemHeightLast,\r
-                               i, node, data, _y = 0, last, n;\r
+                               start      = this.startIndex - this.numItemsPrev,\r
+                               itemH      = this.itemHeightLastEM,\r
+                               i, data, node, _y = 0, last, n;\r
+                       \r
+                       i = this.startRenderIndex = start = start < 0 ? 0 : start;\r
                        \r
-                       i = start = start < 0 ? 0 : start;\r
+                       _y = ( itemH + gapY ) * i;\r
                        \r
                        for( ; i < l; ++i ){\r
-                               if( !( node = uinodes[ i ] ) ){\r
+                               if( !( data = itemNodes[ i ] ) ){\r
                                        node = render.clone( true );\r
                                        this.addAt( i, [ node ] );\r
-                                       data = X_Pair_get( node );\r
+                                       data = itemNodes[ i ] = X_Pair_get( node );\r
                                        // init -> addToParent -> creationComplete\r
                                };\r
                                data.setItemData( dataSource[ i ] );\r
@@ -115,40 +148,42 @@ var XUI_Repeater = XUI_Box.inherits(
                                // 一番最初のループ。ここでページあたりのアイテム数を計算\r
                                if( !itemH && i === start ){\r
                                        itemH = _y - gapY;\r
-                                       this.itemHeightLast  = itemH * X_ViewPort_baseFontSize,\r
+                                       this.itemHeightLastEM = itemH;\r
+                                       this.itemHeightLast   = itemH * X_ViewPort_baseFontSize,\r
                                        // scroller の miniHeight は(例えば)親の高さの300% そこにいくつのアイテムを並べることが出来るか?端数切り上げ\r
                                        this.numItemsParPage = _h / itemH + 0.999 | 0;\r
                                        n    = this.numItems = ( _h * 3 ) / itemH + 0.999 | 0; // TODO boxHeight\r
+                                       this.numItemsPrev    = ( this.numItems - this.numItemsParPage ) / 2 | 0;\r
                                        last = i + n;\r
                                        // データの最後まで、または、開始位置から 3ページ分を生成する\r
                                        l    = last < l ? last : l;\r
                                };\r
                        };\r
                        \r
-                       for( l = uinodes.length; i < l; ++i ){\r
-                               // uinodes[ i ] hide\r
+                       for( l = itemNodes.length; i < l; ++i ){\r
+                               // itemNodes[ i ] hide\r
                        };\r
                        \r
                        // TODO contentHeight は attr を無視する -> 未表示領域につくるアイテム数 GPU の有無で変わる\r
-                       this.contentHeight = _y - gapY;\r
+                       this.contentHeight = dataSource.length * ( itemH + gapY ) - gapY;\r
                },\r
                \r
                onPropertyChange : function( name, newValue ){\r
-                       var uinodes, i, l, uinode, dataList, from;\r
+                       var itemNodes, i, l, uinode, dataList, from;\r
                        \r
                        switch( name ){\r
                                case 'itemRenderer' :\r
-                                       for( uinodes = this.uinodes, i = uinodes && uinodes.length; i; ){\r
-                                               uinodes[ --i ][ 'kill' ]();\r
+                                       for( itemNodes = this.itemNodes, i = itemNodes && itemNodes.length; i; ){\r
+                                               itemNodes[ --i ][ 'kill' ]();\r
                                        };\r
                                        \r
                                case 'dataSource' :\r
-                                       if( uinodes = this.uinodes ){\r
-                                               i = uinodes.length;\r
+                                       if( itemNodes = this.itemNodes ){\r
+                                               i = itemNodes.length;\r
                                                l = this[ 'dataSource' ].length;\r
                                                while( l < i ){\r
-                                                       uinodes[ --i ][ 'kill' ]();\r
-                                                       uinodes.length = i;\r
+                                                       itemNodes[ --i ][ 'kill' ]();\r
+                                                       itemNodes.length = i;\r
                                                };                                              \r
                                        };\r
 \r
@@ -167,7 +202,8 @@ X.UI.Repeater = X.UI.Box.inherits(
                        var supports;\r
                        \r
                        if( XUI_Repeater.prototype.usableAttrs === XUI_Box.prototype.usableAttrs ){\r
-                               XUI_Repeater.prototype.usableAttrs = supports = XUI_Attr_createAttrDef( XUI_Attr_Support, XUI_Layout_Vertical.overrideAttrsForSelf );\r
+                               supports = XUI_Attr_createAttrDef( XUI_Attr_Support, X_UI_Repeater_SUPPORT_ATTRS );\r
+                               XUI_Repeater.prototype.usableAttrs = supports = XUI_Attr_createAttrDef( supports, XUI_Layout_Vertical.overrideAttrsForSelf );\r
                \r
                                XUI_Repeater.prototype.attrClass   = XUI_Attr_preset( XUI_Box.prototype.attrClass, supports );\r
                        };\r
@@ -185,7 +221,13 @@ X.UI.Repeater = X.UI.Box.inherits(
                                                width     : 'auto',\r
                                                minWidth  : '100%',\r
                                                height    : 'auto',\r
-                                               minHeight : '100%'\r
+                                               minHeight : '100%',\r
+                               borderColor : 0x252527,\r
+                               borderWidth : [ 0.15, 0, 0 ],\r
+                               borderStyle : 'solid',\r
+                               height      : 'auto',\r
+                               bgColor     : 0x444643,\r
+                               gapY        : 0.15\r
                                        }));\r
                },\r
                \r
index 5112b46..76f87f9 100644 (file)
@@ -9,9 +9,10 @@ X.UI.List = X.UI.ScrollBox.inherits(
                                {\r
                                        borderColor  : 0x252527,\r
                                        borderWidth  : [ 0.15, 0, 0 ],\r
+                                       borderStyle  : 'solid',\r
                                        height       : 'auto',\r
                                        bgColor      : 0x444643,\r
-                                       gapY         : 0.1,\r
+                                       gapY         : 0.15,\r
                                        scrollSlider : X.UI.Repeater.apply( 0, [ dataSource, itemRenderer ] )\r
                                }\r
                        );\r
index 34820f1..5dacb25 100644 (file)
@@ -1,9 +1,15 @@
+var X_UI_Text_SUPPORT_ATTRS = {\r
+               content   : [ '', XUI_Dirty.CONTENT, XUI_Attr_USER.UINODE, XUI_Attr_Type.STRING ]\r
+};\r
+\r
 var XUI_Text = XUI_AbstractUINode.inherits(\r
        '_Text',\r
        X_Class.NONE,\r
        {\r
                content     : '',\r
                \r
+               usableAttrs     : XUI_Attr_createAttrDef( XUI_AbstractUINode.prototype.usableAttrs, X_UI_Text_SUPPORT_ATTRS ),\r
+               \r
                Constructor : function( user, content ){\r
                        if( !( user[ 'instanceOf' ]( X.UI.Text ) ) ){\r
                                alert( 'Text を継承したインスタンスだけが _Text のオーナーになれます' );\r
@@ -23,6 +29,16 @@ var XUI_Text = XUI_AbstractUINode.inherits(
                        };\r
                        \r
                        XUI_AbstractUINode.prototype.creationComplete.apply( this, arguments );                 \r
+               },\r
+               \r
+               setItemData : function( itemData ){\r
+                       if( this.itemData === itemData ) return;\r
+                       \r
+                       XUI_AbstractUINode.prototype.setItemData.apply( this, arguments );\r
+                       \r
+                       if( X_Type_isObject( itemData = this.itemData ) && this.dataFeild ){\r
+                               this.User.content( itemData[ this.dataFeild ] || '' );\r
+                       };\r
                }\r
        }\r
 );\r