OSDN Git Service

Version 0.6.138, working X.UI.ScrollBox!, fix Node.prev & Node.next.
[pettanr/clientJs.git] / 0.6.x / js / 20_ui / 08_Box.js
1 \r
2 X.UI.Layout.Canvas = X.UI.Layout.create( {\r
3         name : 'CanvasLayout',\r
4         \r
5         overrideAttrsForSelf : {\r
6                 selectable  : false,\r
7                 role        : [ 0, X.UI.Dirty.CLEAN, X.UI.Attr.USER.UINODE, X.UI.Attr.Type.INIT_ONLY | X.UI.Attr.Type.LIST, 'none,chrome,container' ],\r
8                 \r
9                 width       : [ '100%',         X.UI.Dirty.LAYOUT, X.UI.Attr.USER.LAYOUT, X.UI.Attr.Type.LENGTH | X.UI.Attr.Type.PERCENT ],\r
10                 maxWidth    : [ X.UI.Attr.AUTO, X.UI.Dirty.LAYOUT, X.UI.Attr.USER.LAYOUT, X.UI.Attr.Type.LENGTH | X.UI.Attr.Type.PERCENT ],\r
11                 height      : [ 0,              X.UI.Dirty.LAYOUT, X.UI.Attr.USER.LAYOUT, X.UI.Attr.Type.LENGTH | X.UI.Attr.Type.PERCENT ],\r
12                 maxHeight   : [ X.UI.Attr.AUTO, X.UI.Dirty.LAYOUT, X.UI.Attr.USER.LAYOUT, X.UI.Attr.Type.LENGTH | X.UI.Attr.Type.PERCENT ]\r
13         },\r
14         \r
15         overrideAttrsForChild : {\r
16                 left   : true,\r
17                 top    : true,\r
18                 bottom : true,\r
19                 right  : true\r
20         },\r
21         \r
22         calculate : function( data, isNeedsDetection, x, y, w, h ){\r
23                 var uinodes, l, i, _x, _y, _w, _h, node;\r
24 \r
25                 data.preMesure( w, h );\r
26                 \r
27                 if( isNeedsDetection && ( data.boxWidth === X.UI.Attr.AUTO || data.boxHeight === X.UI.Attr.AUTO ) ) return false;\r
28                 \r
29                 _x = data.contentL;\r
30                 _y = data.contentT;\r
31                 _w = data.contentWidth;\r
32                 _h = data.contentHeight;\r
33 \r
34                 if( ( uinodes = data.uinodes ) && ( l = uinodes.length ) ){\r
35                         for( i = 0; i < l; ++i ){\r
36                                 node = uinodes[ i ];\r
37                                 node.calculate( false, _x, _y, _w, _h );\r
38                         };\r
39                 } else\r
40                 if( data.contentHeight === X.UI.Attr.AUTO ){\r
41                         data.contentHeight = data.minContentHeight !== X.UI.Attr.AUTO ? data.minContentHeight : 0;\r
42                 };\r
43                 \r
44                 data.postMesure();\r
45                 data.updateLayout( x + data.boxX, y + data.boxY );\r
46                 \r
47                 return true;\r
48         }\r
49 });\r
50 \r
51 \r
52 X.UI._Box = X.UI._AbstractUINode.inherits(\r
53         'X.UI._Box',\r
54         X_Class.PRIVATE_DATA | X_Class.SUPER_ACCESS, // 現状 super 指定がないとconstructor未定擬時に親のconstructor が使われない\r
55         {\r
56                 supportAttrs    : XUI_Attr_createAttrDef( X.UI._AbstractUINode.prototype.supportAttrs, X.UI.Layout.Canvas.overrideAttrsForSelf ),\r
57                 \r
58                 layout          : null,\r
59                 uinodes         : null,\r
60                 xnodes          : null,\r
61                 \r
62                 hitChildData    : null,\r
63                 pointerChildren : true,\r
64                 through         : false,\r
65 \r
66                 scrollingX      : 0,\r
67                 scrollingY      : 0,\r
68 \r
69                 Constructor : function( layout, args ){\r
70                         var i = 0,\r
71                                 l = args.length || 1,\r
72                                 j = -1,\r
73                                 uinodes, arg, _data, attrs, support, p;\r
74                         \r
75                         //if( !args.length ) args = [ args ];\r
76                         \r
77                         if( !this.User[ 'instanceOf' ]( X.UI.Box ) ){\r
78                                 //throw new Error( 'Box を継承したインスタンスだけが _Box のオーナーになれます' );\r
79                         };                      \r
80                         \r
81                         this.xnode  = X_Doc_create( 'div' );\r
82                         \r
83                         // すでに定義されていればそちらを採用\r
84                         // supportAttrs や attrClass が、layout を元に上書きされているため\r
85                         this.layout = this.layout || layout;\r
86                         \r
87                         for( ; i < l; ++i ){\r
88                                 arg = args[ i ];\r
89                                 if( arg[ 'instanceOf' ] && arg[ 'instanceOf' ]( X.UI.AbstractUINode ) ){\r
90                                         _data = X_Class_getPrivate( arg );\r
91                                         if( !uinodes ) this.uinodes = uinodes = [];\r
92                                         uinodes[ ++j ] = _data;\r
93                                         if( _data.parent ){\r
94                                                 //throw new Error( 'インスタンスはすでに親に追加されています ' + arg );\r
95                                         };\r
96                                 } else\r
97                                 if( arg[ 'instanceOf' ] && arg[ 'instanceOf' ]( Node ) ){\r
98                                         //this.layout = arg;\r
99                                 } else\r
100                                 if( arg[ 'instanceOf' ] && arg[ 'instanceOf' ]( X.UI.Layout.Base ) ){\r
101                                         //this.layout = arg;\r
102                                 } else\r
103                                 if( X_Type_isObject( arg ) ){\r
104                                         if( attrs ){\r
105                                                 attrs = X_Class_override( attrs, arg );\r
106                                         } else {\r
107                                                 attrs = arg;\r
108                                         };\r
109                                 } else {\r
110                                         //throw new Error( 'AbstractUINode を継承したインスタンスを渡してください ' + arg );\r
111                                 };\r
112                         };\r
113                         \r
114                         for( p in attrs ){\r
115                                 if( X_EMPTY_OBJECT[ p ] ) continue;\r
116                                 ( support = this.supportAttrs[ p ] ) && this.setAttr( p, support, attrs[ p ] );\r
117                         };\r
118                 },\r
119         /* Rellay */\r
120                 initialize : function( root, rootData, parent, parentData ){\r
121                         var uinodes = this.uinodes,\r
122                                 i       = uinodes && uinodes.length;\r
123                         this.root       = root;\r
124                         this.rootData   = rootData;\r
125                         this.parent     = parent;\r
126                         this.parentData = parentData;\r
127                         //this.xnode      = X_Doc_create( 'div' );\r
128                         \r
129                         if( i ){\r
130                                 for( ; i; ){\r
131                                         uinodes[ --i ].initialize( root, rootData, this.User, this );\r
132                                 };                              \r
133                         };\r
134                         \r
135                         this.phase = 1;\r
136                         this.User[ 'dispatch' ]( { type : X.UI.Event.INIT } );\r
137                 },\r
138                 \r
139                 addToParent : function( parentXNode ){\r
140                         var uinodes = this.uinodes,\r
141                                 l       = uinodes && uinodes.length,\r
142                                 i;\r
143 \r
144                         parentXNode && parentXNode[ 'append' ]( this.xnode );\r
145                         \r
146                         if( l ){\r
147                                 for( i = 0; i < l; ++i ){\r
148                                         uinodes[ i ].addToParent( this.xnode );\r
149                                 };\r
150                         };\r
151                         \r
152                         this.phase = 2;\r
153                         this.User[ 'dispatch' ]( { type : X.UI.Event.ADDED } );\r
154                 },\r
155                 \r
156         /* Rellay */\r
157                 creationComplete : function(){\r
158                         var uinodes = this.uinodes,\r
159                                 i       = uinodes && uinodes.length;\r
160                         if( i ){\r
161                                 for( ; i; ){\r
162                                         uinodes[ --i ].creationComplete();\r
163                                 };                              \r
164                         };\r
165                         \r
166                         X.UI._AbstractUINode.prototype.creationComplete.apply( this, arguments );\r
167                 },\r
168                 \r
169                 calculate : function( isNeedsDetection, x, y, w, h ){\r
170                         var ret = this.layout.calculate( this, isNeedsDetection, x, y, w, h );                  \r
171                         this.phase = 4;\r
172                         return ret;\r
173                 },\r
174                 \r
175                 capcher : function( x, y ){\r
176                         var uinodes, child, _x, _y, hit, i;\r
177                         if( this.pointerDisabled ) return false;\r
178                         delete this.hitChildData;\r
179                         x -= this.boxX;\r
180                         y -= this.boxY;\r
181                         if( this.pointerChildren && ( uinodes = this.uinodes ) && ( i = uinodes.length ) ){\r
182                                 _x = x - this.scrollingX;\r
183                                 _y = y - this.scrollingY;\r
184                                 for( ; i; ){\r
185                                         child = uinodes[ --i ];\r
186                                         if( !child.pointerDisabled && child.boxX <= _x && _x < child.boxX + child.boxWidth && child.boxY <= _y && _y < child.boxY + child.boxHeight && child.capcher( _x, _y ) ){\r
187                                                 //console.log( 'hit child ' + _x + ' ' + _y + ' boxX:' + child.boxX + ' boxY:' + child.boxY );\r
188                                                 this.hitChildData = child;\r
189                                                 break;\r
190                                         };\r
191                                 };\r
192                         };\r
193                         if( this.through ){\r
194                                 this.hitChildData && !this.hovering && ( this.rootData.hoverList[ this.rootData.hoverList.length ] = this );\r
195                                 return !!this.hitChildData;\r
196                         };\r
197                         hit = 0 <= x && x < this.boxWidth && 0 <= y && y < this.boxHeight;\r
198                         ( this.hitChildData || hit ) && !this.hovering && ( this.rootData.hoverList[ this.rootData.hoverList.length ] = this );\r
199                         if( hit && this.hitChildData === null ) this.rootData.targetNodeData = this;\r
200                         return hit || !!this.hitChildData;\r
201                 },\r
202                 \r
203                 addAt : function( index, _uinodes ){\r
204                         //console.log( '# AddAt ' + this.phase )\r
205                         var uinodes = this.uinodes,\r
206                                 num     = uinodes.length,\r
207                                 p1      = 1 <= this.phase,\r
208                                 p2      = 2 <= this.phase,\r
209                                 p3      = 3 <= this.phase,\r
210                                 i       = 0,\r
211                                 _p1, _p2,\r
212                                 l, data;\r
213 \r
214                         //console.log( '### AddAt ' + this.phase )\r
215                         for( l = _uinodes.length; i < l; ++i ){\r
216                                 data = X_Class_getPrivate( _uinodes[ i ] );\r
217                                 _p1  = p1 && data.phase < 1;\r
218                                 _p2  = p2 && data.phase < 2;\r
219                                 _p1 && data.initialize( this.root, this.rootData, this.User, this );\r
220                                 if( index <= num ){\r
221                                         // _p2 && this.xnode.insertBefore( data.xnode, uinodes[ index + i ].xnode );\r
222                                         _p2 && uinodes[ index + i ].xnode[ 'prev' ]( data.xnode );\r
223                                         _p2 && data.addToParent( this.xnode );\r
224                                         uinodes.splice( index + i, 0, data );\r
225                                 } else {\r
226                                         _p2 && data.addToParent( this.xnode );\r
227                                         uinodes[ uinodes.length ] = data;       \r
228                                 };\r
229                                 p3 && data.phase < 3 && data.creationComplete();\r
230                         };\r
231                         4 <= this.phase && this.rootData.reserveCalc();\r
232                 },\r
233                 \r
234                 remove : function( _uinodes ){\r
235                         //console.log( '# AddAt ' + this.phase )\r
236                         var uinodes = this.uinodes,\r
237                                 i       = _uinodes.length,\r
238                                 n, data;\r
239 \r
240                         //console.log( '### AddAt ' + this.phase )\r
241                         for( ; i; ){\r
242                                 data = X_Class_getPrivate( _uinodes[ --i ] );\r
243                                 if( ( n = uinodes.indexOf( data ) ) !== -1 ){\r
244                                         uinodes.splice( n, 1 );\r
245                                         data._remove();\r
246                                 };\r
247                         };\r
248                         4 <= this.phase && this.rootData.reserveCalc();\r
249                 },\r
250                 \r
251                 removeAt : function( from, length ){\r
252                         var uinodes = this.uinodes,\r
253                                 i       = uinodes.length,\r
254                                 to      = from + ( X_Type_isNumber( length ) && 1 <= length ? length : 1 ),\r
255                                 node;\r
256                         for( ; i; ){\r
257                                 node = uinodes[ --i ];\r
258                                 if( from <= i && i < to ){\r
259                                         uinodes.splice( i, 1 );\r
260                                         node._remove();\r
261                                 };\r
262                         };\r
263                         4 <= this.phase && this.rootData.reserveCalc();\r
264                 },\r
265                 \r
266                 _remove : function(){\r
267                         var uinodes = this.uinodes,\r
268                                 i       = uinodes.length;\r
269                         for( ; i; ){ uinodes[ --i ]._remove(); };\r
270                                         \r
271                         switch( this.phase ){\r
272                                 case 4:\r
273                                 case 3:\r
274                                 case 2:\r
275                                         this.xnode[ 'remove' ]();\r
276                                 case 1:\r
277                                         delete this.root;\r
278                                         delete this.rootData;\r
279                                         delete this.parent;\r
280                                         delete this.parentData;\r
281                                         delete this.xnode;\r
282                         };\r
283                         delete this.phase;\r
284                 }\r
285         }\r
286 );\r
287 \r
288 X.UI.Box = X.UI.AbstractUINode.inherits(\r
289         'Box',\r
290         X_Class.SUPER_ACCESS,\r
291         X.UI._Box,\r
292         {\r
293                 Constructor : function(){\r
294                         X_Class_newPrivate( this, X.UI.Layout.Canvas, arguments );\r
295                 },\r
296                 \r
297                 add : function( node /* , node, node ... */ ){\r
298                         X_Class_getPrivate( this ).addAt( this.numNodes() + 1, Array.prototype.slice.call( arguments ) );\r
299                         return this;\r
300                 },\r
301                 addAt : function( index, node /* , node, node ... */ ){\r
302                         if( index < 0 ) index = 0;\r
303                         X_Class_getPrivate( this ).addAt( arguments[ 0 ], Array.prototype.slice.call( arguments, 1 ) );\r
304                         return this;\r
305                 },\r
306                 remove : function( node /* , node, node ... */ ){\r
307                         X_Class_getPrivate( this )[ 'remove' ]( Array.prototype.slice.call( arguments ) );\r
308                         return this;\r
309                 },\r
310                 removeAt : function( from, length ){\r
311                         X_Class_getPrivate( this ).removeAt( from, length );\r
312                         return this;\r
313                 },\r
314                 getNodesByClass : function( klass ){\r
315                         var ret     = [],\r
316                                 uinodes = X_Class_getPrivate( this ).uinodes,\r
317                                 i, l, node;\r
318                         if( !uinodes || uinodes.length === 0 ) return ret;\r
319                         for( i = 0, l = uinodes.length; i < l; ++i ){\r
320                                 node = uinodes[ i ].User;\r
321                                 if( node[ 'instanceOf' ]( klass ) ) ret[ ret.length ] = node;\r
322                         };\r
323                         return ret;\r
324                 },\r
325                 getFirstChild : function(){\r
326                         return this.getNodeAt( 0 );\r
327                 },\r
328                 getLastChild : function(){\r
329                         var uinodes = X_Class_getPrivate( this ).uinodes;\r
330                         return uinodes && uinodes.length && uinodes[ uinodes.length - 1 ].User || null;\r
331                 },\r
332                 getNodeAt : function( index ){\r
333                         if( index < 0 ) return null;\r
334                         var uinodes = X_Class_getPrivate( this ).uinodes;\r
335                         return uinodes && uinodes[ index ].User || null;\r
336                 },\r
337                 numNodes : function(){\r
338                         var uinodes = X_Class_getPrivate( this ).uinodes;\r
339                         return uinodes && uinodes.length || 0;\r
340                 }\r
341         }\r
342 );\r
343 \r
344 /*\r
345  * layout が設定されている Box のサブクラスに対して、layout を指定できない.\r
346  * \r
347  */\r
348 X.UI.Box.presets = function(){\r
349         var args   = arguments,\r
350                 i      = 0,\r
351                 l      = args.length,   \r
352                 shadow = X_Class_getClassDef( this ).privateClass,\r
353                 layout = shadow.prototype.layout,\r
354                 arg, attrs, supports, klass, klassDef, privateKlass, boxName;\r
355                         \r
356         for( ; i < l; ++i ){\r
357                 arg = args[ i ];\r
358                 if( !arg ) continue;\r
359                 // レイアウトの preset ができるのは layout が未定義な Box だけ\r
360                 if( !shadow.prototype.layout && arg[ 'instanceOf' ] && arg[ 'instanceOf' ]( X.UI.Layout.Base ) ){\r
361                         layout = arg;\r
362                 } else\r
363                 if( ( klassDef = X_Class_getClassDef( arg ) ) && klassDef.isPrivate ){\r
364                         privateKlass = arg;\r
365                         layout = privateKlass.prototype.layout;\r
366                 } else\r
367                 if( X_Type_isObject( arg ) ){\r
368                         if( attrs ){\r
369                                 X_Class_override( attrs, arg, true );\r
370                         } else {\r
371                                 attrs = arg;\r
372                         };\r
373                 } else\r
374                 if( X_Type_isString( arg ) ){\r
375                         boxName = arg;\r
376                 };\r
377         };\r
378         \r
379         if( privateKlass ){\r
380                 supports = XUI_Attr_createAttrDef( privateKlass.prototype.supportAttrs, layout.overrideAttrsForSelf );\r
381                 \r
382                 klass = this.inherits( privateKlass );\r
383                 privateKlass.prototype.supportAttrs = supports,\r
384                 privateKlass.prototype.attrClass    = X.UI.Attr.preset( privateKlass.prototype.attrClass, supports, attrs );\r
385         } else {\r
386                 supports = XUI_Attr_createAttrDef( shadow.prototype.supportAttrs, layout.overrideAttrsForSelf );\r
387                 \r
388                 klass = this.inherits(\r
389                         boxName,\r
390                         shadow.inherits(\r
391                                 {\r
392                                         layout       : layout,\r
393                                         supportAttrs : supports,\r
394                                         attrClass    : X.UI.Attr.preset( shadow.prototype.attrClass, supports, attrs )\r
395                                 }\r
396                         )\r
397                 );              \r
398         };\r
399 \r
400         klass.presets = this.presets || X.UI.Box.presets;\r
401         \r
402         return klass;\r
403 };\r