OSDN Git Service

3f980f800acca4e74a47cc74de1e7a086ce2dbf0
[pettanr/clientJs.git] / 0.6.x / js / 20_ui / 16_Repeater.js
1 var X_UI_Repeater_SUPPORT_ATTRS = {\r
2                 dataSource   : [ null, XUI_Dirty.LAYOUT, XUI_Attr_USER.UINODE, XUI_Attr_Type.OBJECT ],\r
3                 itemRenderer : [ null, XUI_Dirty.LAYOUT, XUI_Attr_USER.UINODE, XUI_Attr_Type.OBJECT ]\r
4 };\r
5 \r
6 var XUI_Repeater = XUI_Box.inherits(\r
7         '_Repeater',\r
8         X_Class.NONE,\r
9         {\r
10                 layout       : XUI_Layout_Vertical,\r
11                 \r
12                 dataSource   : null, // Array.<object>, Array.<ItemData>\r
13                 \r
14                 itemRenderer     : null,\r
15                 \r
16                 \r
17                 startIndex       : 0,\r
18                 startRenderIndex : 0,\r
19                 numItemsParPage  : 0,\r
20                 numItems         : 0,\r
21                 \r
22                 Constructor : function( user, dataSource, itemRenderer, attr ){\r
23                         this.Super( user, null, [ attr ] );\r
24                         this.dataSource   = dataSource;\r
25                         this.itemRenderer = itemRenderer;\r
26                 },\r
27                 \r
28                 /*\r
29                  * ここに来るのは、初描画とリサイズ\r
30                  */\r
31                 calculate : function( isNeedsDetection, x, y, allowedW, allowedH ){\r
32                         var dataSource = this[ 'dataSource' ];\r
33 \r
34                         if( allowedW + allowedH === XUI_Attr_AUTO ) return false;\r
35                 \r
36                         this.scrollPortWidth  = allowedW;\r
37                         this.scrollPortHeight = allowedH;                       \r
38                         \r
39                         this.preMesure( allowedW, allowedH );\r
40                         \r
41                         if( dataSource && dataSource.length ){\r
42                                 this.updateItemRenderer( this.contentWidth, allowedH );\r
43                         } else\r
44                         if( this.contentHeight === XUI_Attr_AUTO ){\r
45                                 this.contentHeight = this.contentHeightMin !== XUI_Attr_AUTO ? this.contentHeightMin : 0;\r
46                         };\r
47                         \r
48                         this.postMesure();\r
49         \r
50                         if( !isNeedsDetection ){\r
51                                 this.boxX += x;\r
52                                 this.boxY += y;\r
53                         };\r
54                         return true;\r
55                 },\r
56                 \r
57                 handleEvent : function( e ){\r
58                         var scrollBox, scrollY, dataSource, offsetY, startIndex, maxIndex, offset, uinodes;\r
59                         \r
60                         switch( e.type ){\r
61                                 case XUI_Event.SCROLL_END :\r
62                                         scrollBox  = this.parentData;\r
63                                         scrollY    = scrollBox.scrollY;\r
64                                         dataSource = this[ 'dataSource' ];\r
65                                         uinodes    = this.uinodes;\r
66                                         // transition Y を 0 付近に。\r
67                                         offsetY    = scrollY % this.itemHeightLast;\r
68                                         scrollBox.scrollTo( 0, offsetY, 0, '', 0 ); // anime無し\r
69                                         // startIndex の計算\r
70                                         startIndex = scrollY / this.itemHeightLast | 0;\r
71                                         maxIndex   = dataSource.length <= this.numItems ? 0 : dataSource.length - this.numItems;\r
72                                         startIndex =\r
73                                                 startIndex < 0 ? 0 :\r
74                                                 maxIndex < startIndex ? maxIndex : startIndex;\r
75                                         // アイテムの座標の修正とレンジ外のアイテムを配列内で再配置\r
76                                         offset = startIndex - this.startIndex; // visible な stratIndex renderStartIndex\r
77                                         \r
78                                         if( 0 < offset ){\r
79                                                 this.addAt( last, uinodes.splice( 0, offset ) );\r
80                                         } else\r
81                                         if( offset < 0 ){\r
82                                                 this.addAt( 0, uinodes.splice( uinodes.length - offset ) );\r
83                                         };\r
84                                         // 再配置されたアイテムにitemData のセット\r
85                                         this.updateItemRenderer( this.contentWidth, this.scrollPortHeight );\r
86                                         break;\r
87                         };\r
88                 },\r
89                 \r
90                 updateItemRenderer : function( _w, _h ){\r
91                         var uinodes    = this.uinodes || ( this.uinodes = [] ),\r
92                                 attrs      = this.attrObject || this.attrClass.prototype,\r
93                                 gapY       = XUI_AbstractUINode_calcValue( attrs[ this.usableAttrs.gapY.No ], _w ),\r
94                                 dataSource = this[ 'dataSource' ],\r
95                                 render     = this[ 'itemRenderer' ],\r
96                                 l          = dataSource.length,\r
97                                 start      = this.startIndex - ( this.numItems - this.numItemsParPage ) / 2 | 0,\r
98                                 itemH      = this.itemHeightLast,\r
99                                 i, node, data, _y = 0, last, n;\r
100                         \r
101                         i = start = start < 0 ? 0 : start;\r
102                         \r
103                         for( ; i < l; ++i ){\r
104                                 if( !( node = uinodes[ i ] ) ){\r
105                                         node = render.clone( true );\r
106                                         this.addAt( i, [ node ] );\r
107                                         data = X_Pair_get( node );\r
108                                         // init -> addToParent -> creationComplete\r
109                                 };\r
110                                 data.setItemData( dataSource[ i ] );\r
111                                 \r
112                                 data.calculate( false, 0, _y, _w, _h );\r
113                                 _y += ( itemH || data.boxHeight ) + gapY;\r
114                                 \r
115                                 // 一番最初のループ。ここでページあたりのアイテム数を計算\r
116                                 if( !itemH && i === start ){\r
117                                         itemH = _y - gapY;\r
118                                         this.itemHeightLast  = itemH * X_ViewPort_baseFontSize,\r
119                                         // scroller の miniHeight は(例えば)親の高さの300% そこにいくつのアイテムを並べることが出来るか?端数切り上げ\r
120                                         this.numItemsParPage = _h / itemH + 0.999 | 0;\r
121                                         n    = this.numItems = ( _h * 3 ) / itemH + 0.999 | 0; // TODO boxHeight\r
122                                         last = i + n;\r
123                                         // データの最後まで、または、開始位置から 3ページ分を生成する\r
124                                         l    = last < l ? last : l;\r
125                                 };\r
126                         };\r
127                         \r
128                         for( l = uinodes.length; i < l; ++i ){\r
129                                 // uinodes[ i ] hide\r
130                         };\r
131                         \r
132                         // TODO contentHeight は attr を無視する -> 未表示領域につくるアイテム数 GPU の有無で変わる\r
133                         this.contentHeight = _y - gapY;\r
134                 },\r
135                 \r
136                 onPropertyChange : function( name, newValue ){\r
137                         var uinodes, i, l, uinode, dataList, from;\r
138                         \r
139                         switch( name ){\r
140                                 case 'itemRenderer' :\r
141                                         for( uinodes = this.uinodes, i = uinodes && uinodes.length; i; ){\r
142                                                 uinodes[ --i ][ 'kill' ]();\r
143                                         };\r
144                                         \r
145                                 case 'dataSource' :\r
146                                         if( uinodes = this.uinodes ){\r
147                                                 i = uinodes.length;\r
148                                                 l = this[ 'dataSource' ].length;\r
149                                                 while( l < i ){\r
150                                                         uinodes[ --i ][ 'kill' ]();\r
151                                                         uinodes.length = i;\r
152                                                 };                                              \r
153                                         };\r
154 \r
155                                         \r
156                                         break;\r
157                         };\r
158                 }\r
159         }\r
160 );\r
161 \r
162 X.UI.Repeater = X.UI.Box.inherits(\r
163         'Repeater',\r
164         X_Class.NONE,\r
165         {\r
166                 Constructor : function( dataSource, itemRenderer ){\r
167                         var supports;\r
168                         \r
169                         if( XUI_Repeater.prototype.usableAttrs === XUI_Box.prototype.usableAttrs ){\r
170                                 XUI_Repeater.prototype.usableAttrs = supports = XUI_Attr_createAttrDef( XUI_Attr_Support, XUI_Layout_Vertical.overrideAttrsForSelf );\r
171                 \r
172                                 XUI_Repeater.prototype.attrClass   = XUI_Attr_preset( XUI_Box.prototype.attrClass, supports );\r
173                         };\r
174                         \r
175                         // dataProvider\r
176                         // itemBase parent に追加されている uinode は不可\r
177                         // minHeight=300% height=auto\r
178                         X_Pair_create( this,\r
179                                 XUI_Repeater(\r
180                                         this,\r
181                                         dataSource, itemRenderer,\r
182                                         {\r
183                                                 name      : 'ScrollBox-Scroller',\r
184                                                 role      : 'container',\r
185                                                 width     : 'auto',\r
186                                                 minWidth  : '100%',\r
187                                                 height    : 'auto',\r
188                                                 minHeight : '100%'\r
189                                         }));\r
190                 },\r
191                 \r
192                 getItemDataAt : function(){\r
193                         \r
194                 },\r
195                 \r
196                 add : function( /* node, node, node ... */ ){\r
197                 },\r
198                 addAt : function( index /* , node , node, node ... */ ){\r
199                 },\r
200                 remove : function( /* node, node, node ... */ ){\r
201                 },\r
202                 removeAt : function( from, length ){\r
203                 },\r
204                 getNodesByClass : function( klass ){\r
205                 },\r
206                 getFirstChild : function(){\r
207                 },\r
208                 getLastChild : function(){\r
209                 },\r
210                 getNodeAt : function( index ){\r
211                 },\r
212                 numNodes : function(){\r
213                         var uinodes = X_Pair_get( this ).uinodes;\r
214                         return uinodes && uinodes.length || 0;\r
215                 }\r
216 \r
217         }\r
218 );\r