OSDN Git Service

Version 0.6.23, remove AbstractBox(AbstractDisplayContainer), working ie-filter-fix.
[pettanr/clientJs.git] / 0.6.x / js / ui / 06_AbstractUINode.js
1 var _AbstractUINode = X.EventDispatcher.inherits(\r
2         '_AbstractUINode',\r
3         X.Class.ABSTRACT | X.Class.PRIVATE_DATA,\r
4         {\r
5                 phase         : 0,\r
6                 root          : null,\r
7                 rootData      : null,\r
8                 parent        : null,\r
9                 parentData    : null,\r
10                 rawElement    : null,\r
11                 rawStyle      : null,\r
12                 \r
13                 //events        : null, // X.EventDispatcher で設定される\r
14                 reserveEvents : null,\r
15                 gesture       : null,\r
16                 //elmScroll     : null,\r
17                 //elmScroller   : null,\r
18                 //elmScrollbar  : null,\r
19                                 \r
20                 style         : null,\r
21                 styleData     : null,\r
22                 forChrome     : false, // メッキ\r
23 \r
24                 x              : 0,\r
25                 y              : 0,\r
26                 w              : 0,\r
27                 h              : 0,\r
28                 t              : 0, // top\r
29                 l              : 0, // left\r
30                 b              : 0, // bottom\r
31                 r              : 0, // right\r
32                 absoluteX      : 0,\r
33                 absoluteY      : 0,\r
34                 //_scrollX       : 0,\r
35                 //_scrollY       : 0,\r
36                 scrollingX     : 0,\r
37                 scrollingY     : 0,\r
38                 _cursor        : '',\r
39                 hitChildData   : null,\r
40                 hitSelf        : false,\r
41                 _disabled      : false,\r
42                 _childDisabled : false,\r
43                 through        : false,\r
44                 clip           : false,\r
45                 hover          : false,\r
46                 hoverStyleName : null,\r
47                 isHover        : false,\r
48                 scroll         : false,\r
49                 dragdrop       : false,\r
50                 tooltip        : null,\r
51                 \r
52                 _content          : null,\r
53                 updateContent     : false,\r
54                 \r
55                 boxWidth          : 0,\r
56                 boxHeight         : 0,\r
57                 contentL          : 0,\r
58                 contentT          : 0,\r
59                 contentR          : 0,\r
60                 contentB          : 0,\r
61                 boxSizingOffsetLR : 0,\r
62                 boxSizingOffsetTB : 0,          \r
63                 contentWidth      : 0,\r
64                 minContentWidth   : 0,\r
65                 maxContentWidth   : AUTO,\r
66                 lastContentWidth  : -1,\r
67                 contentHeight     : 0,\r
68                 minContentHeight  : 0,\r
69                 maxContentHeight  : AUTO,\r
70                 \r
71                 // :hover, :focus, :disabled\r
72                 \r
73                 initialize : function( root, rootData, parent, parentData ){\r
74                         this.root       = root;\r
75                         this.rootData   = rootData;\r
76                         this.parent     = parent;\r
77                         this.parentData = parentData;\r
78                         this.rawElement = X.Dom.Node.create( 'div' );\r
79                         \r
80                         this.styleData.initialize();\r
81                         \r
82                         this.phase = 1;\r
83                         this.dispatch( { type : X.UI.Event.INIT } );\r
84                 },\r
85                 \r
86                 addToParent : function( parentElement ){\r
87                         //parentElement && parentElement.appendChild( this.rawElement );\r
88                         parentElement && parentElement.append( this.rawElement );\r
89                         \r
90                         this.phase = 2;\r
91                         this.dispatch( { type : X.UI.Event.ADDED } );\r
92                 },\r
93 \r
94         /* Rellay\r
95                 afterAddition : function(){\r
96                         this.styleData.afterAddition();\r
97                         \r
98                         this.phase = 3;\r
99                         this.dispatch( { type : X.UI.Event.CREATION_COMPLETE } );\r
100                 }, */\r
101                 \r
102                 creationComplete : function(){\r
103                         if( this.phase < 3 ) return;\r
104                         \r
105                         var nodes  = this.nodes,\r
106                                 events = this.reserveEvents,\r
107                                 l, i;\r
108                         if( nodes ){\r
109                                 for( i = 0, l = nodes.length; i < l; ++i ){\r
110                                         nodes[ i ].creationComplete();\r
111                                 };\r
112                         };\r
113                         this.mesure();\r
114                         \r
115                         // this.scroll === true && ScrollBarManager.register( this );\r
116                         \r
117                         // html 要素が親に追加されるまで控えていたイベントの登録\r
118                         if( events && ( l = events.length ) ){\r
119                                 for( i = 0; i < l; ++i ){\r
120                                         this.listen.apply( this, events[ i ] );\r
121                                 };\r
122                                 events.length = 0;\r
123                                 delete this.reserveEvents;\r
124                         };\r
125                 },\r
126                 \r
127                 mesure : function(){\r
128                         var elm = this.rawElement,\r
129                                 x, y, w, h, parent;\r
130                         if( elm ){\r
131                                 w = elm.width();//w = elm.offsetWidth;\r
132                                 h = elm.height();//h = elm.offsetHeight;\r
133                                 x = elm.x();//x = elm.offsetLeft;\r
134                                 y = elm.y();//y = elm.offsetTop;                                \r
135                                 if( this.x !== x || this.y !== y || this.w !== w || this.h !== h ){\r
136                                         this.x = x;\r
137                                         this.y = y;\r
138                                         this.w = w;\r
139                                         this.h = h;\r
140                                         ( parent = this.parentData ) && this.updateAbsoluteXY( parent.absoluteX, parent.absoluteY );\r
141                                 };                      \r
142                         };\r
143                         this.updateRectangle();\r
144                 },\r
145                 \r
146                 updateAbsoluteXY : function( x, y /* , scrollX, scrollY */ ){\r
147                         var nodes = this.nodes, i;\r
148                         this.absoluteX = x = this.x + x;\r
149                         this.absoluteY = y = this.y + y;\r
150                         if( !nodes ) return;\r
151                         for( i = nodes.length; i; ){\r
152                                 nodes[ --i ].updateAbsoluteXY( x, y );\r
153                         };\r
154                 },\r
155                 \r
156                 updateRectangle : function(){\r
157                         var w = this.w, h = this.h, x = this.x, y = this.y,\r
158                                 l = x, t = y, r = x + w, b = y + h,\r
159                                 nodes = this.nodes, i, node;\r
160                                 \r
161                         if( nodes && this.clip === false ){\r
162                                 for( i = nodes.length; i; ){\r
163                                         node = nodes[ --i ];\r
164                                         if( node.l + x < l ) l = x + node.l;\r
165                                         if( node.t + y < t ) t = y + node.t;\r
166                                         if( r < node.r + x ) r = x + node.r;\r
167                                         if( b < node.b + y ) b = y + node.b;\r
168                                 };\r
169                         };\r
170                         // update\r
171                         if( b !== this.b || r !== this.r || t !== this.t || l !== this.l ){\r
172                                 this.l = l;\r
173                                 this.t = t;\r
174                                 this.r = r;\r
175                                 this.b = b;\r
176                                 this.parentData && this.parentData.clip === false && this.parentData.updateRectangle();\r
177                         };\r
178                 },\r
179                 \r
180                 capcher : function( x, y ){\r
181                         var nodes, child, _x, _y, hit, i;\r
182                         if( this._disabled === true ) return false;\r
183                         delete this.hitChildData;\r
184                         x -= this.x;\r
185                         y -= this.y;\r
186                         // この部分 Box に移動\r
187                         if( nodes = this.nodes ){\r
188                                 _x = x - this.scrollingX;\r
189                                 _y = y - this.scrollingY;\r
190                                 for( i = nodes.length; i; ){\r
191                                         child = nodes[ --i ];\r
192                                         if( child._disabled === false && child.l <= _x && _x < child.r && child.t <= _y && _y < child.b && child.capcher( _x, _y ) === true ){\r
193                                                 this.hitChildData = child;\r
194                                                 break;\r
195                                         };\r
196                                 };\r
197                         };\r
198                         if( this.through === true ){\r
199                                 this.hitChildData && this.hitSelf === false && this.rootData.hoverList.push( this );\r
200                                 return !!this.hitChildData;\r
201                         };\r
202                         hit = 0 <= x && x < this.w && 0 <= y && y < this.h;\r
203                         ( this.hitChildData || hit ) && this.hitSelf === false && this.rootData.hoverList.push( this );\r
204                         if( hit === true && this.hitChildData === null ) this.rootData.targetNodeData = this;\r
205                         return hit || !!this.hitChildData;\r
206                 },\r
207                 \r
208                 _remove : function(){\r
209                         switch( this.phase ){\r
210                                 case 4:\r
211                                 case 3:\r
212                                         //this.styleData.afterAddition();\r
213                                 case 2:\r
214                                         //this.rawElement.parentNode.removeChild( this.rawElement );\r
215                                         this.rawElement.remove();\r
216                                 case 1:\r
217                                         //this.styleData.initialize();\r
218                                         delete this.root;\r
219                                         delete this.rootData;\r
220                                         delete this.parent;\r
221                                         delete this.parentData;\r
222                                         delete this.rawElement;\r
223                         };\r
224                         delete this.phase;\r
225                 },\r
226                 //killed\r
227                 \r
228                 \r
229                 content : function( v ){\r
230                         if( Type.isString( v ) === true ){\r
231                                 if( !this.rawText || this.rawText.data !== v ){\r
232                                         this._content = v;\r
233                                         this.updateContent = true;\r
234                                 };\r
235                                 return this.User;\r
236                         } else\r
237                         if( v === null ){\r
238                                 if( this._content !== v && this.rawText ){\r
239                                         this.updateContent = true;\r
240                                 };\r
241                                 delete this._content;\r
242                                 return this.User;\r
243                         };\r
244                         if( this._content || this._content === null ) return this._content;\r
245                         if( this.rawText ) return this.rawText.data;\r
246                         return null;\r
247                 },\r
248                 paint : function( dirty ){\r
249                         var content = this._content,\r
250                                 style   = this.styleData;                               \r
251                         if( this.updateContent === true || ( style && style.hasPaint === true ) ){\r
252                                 if( !this.rawElement ){\r
253                                         this.rawElement = DOM.createDiv();\r
254                                         this.__parent.addDisplayElement( this );\r
255                                 };\r
256                                 dirty !== 0 && this.commitStyle();                      \r
257                                 if( this.updateContent === true ){\r
258                                         if( content !== null ){\r
259                                                 if( !this.rawText ){\r
260                                                         this.rawText = DOM.cerateText();\r
261                                                         this.rawElement.appendChild( this.rawText );\r
262                                                 };\r
263                                                 this.rawText.data = content;                                                    \r
264                                         } else\r
265                                         if( this.rawText ){\r
266                                                 DOM.correct( this.rawText );\r
267                                                 delete this.rawText;\r
268                                                 delete this.contentWidth;\r
269                                                 delete this.conetntHeight;\r
270                                                 delete this.scrollWidth;                                                        \r
271                                                 delete this.scrollHeight;\r
272                                         };                                      \r
273                                 };\r
274                         } else\r
275                         if( this.rawElement && content === null && ( !style || style.hasPaint === false ) ){\r
276                                 this.__parent.removeDisplayElement( this );\r
277                                 DOM.correct( this.rawElement );\r
278                                 delete this.contentWidth;\r
279                                 delete this.conetntHeight;\r
280                         };\r
281                 },\r
282                 commitStyle : function(){\r
283                         var css;\r
284                         if( this.rawElement ){\r
285                                 css = this.styleData ? this.styleData.cssText( this ) : '';\r
286                                 if( this.contentWidth  !== AUTO ) css += 'width:'  + this.contentWidth  + 'px';\r
287                                 if( this.contentHeight !== AUTO ) css += 'height:' + this.contentHeight + 'px';\r
288                                 //this.rawElement.style.cssText = css;\r
289                                 this.rawElement.cssText( css );\r
290                         };\r
291                 },\r
292                 /*\r
293                  * 親の サイズを元に自身のサイズを計算していく\r
294                  */\r
295                 preMesure : function( allowW, allowH ){\r
296                         var style    = this.styleData,\r
297                                 styles, calc, box, min, max,\r
298                                 contentW, contentH, allowSize, boxMinus,\r
299                                 paddingT, paddingR, paddingB, paddingL,\r
300                                 borderT, borderR, borderB, borderL;//,\r
301                                 //marginT, marginR, marginB, marginL;\r
302 \r
303                         if( style ){\r
304                                 styles   = style.data;\r
305                                 calc     = _AbstractUINode.calcValue;\r
306                                 box      = styles[ X.Css.AttrNo.sizing ];\r
307                                 \r
308                                 // Width が確定するパターン\r
309                                 // 自身が constraintW の場合 親が AUTO ではない\r
310                                 // 自身が constraintW でない場合自身が  AUTO はなくかつ親 が AUTO の場合 or 自身は % でない\r
311                                 if( style.constraintW ? allowW !== AUTO : !style.autoWidth && ( allowW !== AUTO || !style.percentWidth ) ){\r
312                                         if( style.constraintW ){ // 制約レイアウト\r
313                                                 contentW = allowW - calc( styles[ X.Css.AttrNo.left ], allowW ) - calc( styles[ X.Css.AttrNo.right ], allowW );\r
314                                         } else {\r
315                                                 contentW = _AbstractUINode.finalValue( styles[ X.Css.AttrNo.width ], styles[ X.Css.AttrNo.minWidth ], styles[ X.Css.AttrNo.maxWidth ], allowW );                                        \r
316                                         };\r
317                                         paddingR = calc( styles[ X.Css.AttrNo.padding + 1 ], allowW );\r
318                                         paddingL = calc( styles[ X.Css.AttrNo.padding + 3 ], allowW );\r
319                                         borderR  = styles[ X.Css.AttrNo.border + 1 ];\r
320                                         borderL  = styles[ X.Css.AttrNo.margin + 3 ];\r
321                                         // marginR  = calc( styles[ X.Css.AttrNo.margin + 1 ], allowW );\r
322                                         // marginL  = calc( styles[ X.Css.AttrNo.margin + 3 ], allowW );\r
323                                         boxMinus = 0;\r
324                                         switch( box ){\r
325                                                 //case 3 : // margin-box\r
326                                                 //       boxMinus = - marginR - marginL;\r
327                                                 case 2 : // border-box\r
328                                                          boxMinus -= borderR + borderL;\r
329                                                 case 1 : // padding-box\r
330                                                          boxMinus -= paddingR + paddingL;\r
331                                                 // case 0 : // content-box\r
332                                         };\r
333                                         this.contentL     = /* marginL + */ borderL + paddingL;\r
334                                         this.contentR     = /* marginR + */ borderR + paddingR;         \r
335                                         this.contentWidth = contentW + boxMinus;\r
336                                         this.boxWidth     = contentW - boxMinus + this.contentL + this.contentR;\r
337                                         this.boxSizingOffsetLR = boxMinus;\r
338                                 } else {\r
339                                         this.boxWidth = this.contentWidth = AUTO;\r
340                                         min = styles[ X.Css.AttrNo.minWidth ];\r
341                                         max = styles[ X.Css.AttrNo.maxWidth ];\r
342                                         this.minContentWidth = 1 <= min ? min : 0;\r
343                                         this.maxContentWidth = 1 <= max ? max : AUTO;\r
344                                         delete this.boxSizingOffsetLR;\r
345                                 };\r
346                                 \r
347                                 // Height\r
348                                 if( style.constraintH ? allowH !== AUTO : !style.autoHeight && ( allowH !== AUTO || !style.percentHeight ) ){\r
349                                         if( style.constraintH ){ // 制約レイアウト\r
350                                                 contentH = allowH - calc( styles[ X.Css.AttrNo.top ], allowH ) - calc( styles[ X.Css.AttrNo.bottom ], allowH );\r
351                                         } else {\r
352                                                 contentH = _AbstractUINode.finalValue( styles[ X.Css.AttrNo.height ], styles[ X.Css.AttrNo.minHeight ], styles[ X.Css.AttrNo.maxHeight ], allowH );\r
353                                         };\r
354                                         allowSize = styles[ X.Css.AttrNo.pageBox ] === true ? allowH : allowW;\r
355                                         paddingT  = calc( styles[ X.Css.AttrNo.padding + 0 ], allowSize );// paddingTRBL の % 指定は 最大幅に対して TB でも幅に対して\r
356                                         paddingB  = calc( styles[ X.Css.AttrNo.padding + 2 ], allowSize );\r
357                                         borderT   = styles[ X.Css.AttrNo.border + 0 ];\r
358                                         borderB   = styles[ X.Css.AttrNo.border + 2 ];\r
359                                         // marginT   = calc( styles[ X.Css.AttrNo.margin + 0 ], allowSize );// marginTRBL の % 指定は 最大幅に対して TB でも幅に対して\r
360                                         // marginB   = calc( styles[ X.Css.AttrNo.margin + 2 ], allowSize );\r
361                                         this.boxHeight = contentH;\r
362                                         boxMinus = 0;\r
363                                         switch( box ){\r
364                                                 // case 3 : // margin-box\r
365                                                          // boxMinus = - marginT - marginR;\r
366                                                 case 2 : // border-box\r
367                                                          boxMinus  = borderT + borderB;\r
368                                                 case 1 : // padding-box\r
369                                                          boxMinus -= paddingT + paddingB;\r
370                                                 // case 0 : // content-box\r
371                                         };                      \r
372                                         this.contentT      = /* marginT + */ borderT + paddingT;\r
373                                         this.conetntB      = /* marginB + */ borderB + paddingB;                        \r
374                                         this.contentHeight = contentH + boxMinus;\r
375                                         this.boxHeight     = contentH - boxMinus + this.contentT + this.conetntB;\r
376                                         this.boxSizingOffsetTB = boxMinus;\r
377                                 } else {\r
378                                         this.boxHeight = this.contentHeight = AUTO;\r
379                                         min = styles[ X.Css.AttrNo.minHeight ];\r
380                                         max = styles[ X.Css.AttrNo.maxHeight ];\r
381                                         this.minContentHeight = 1 <= min ? min : 0;\r
382                                         this.maxContentHeight = 1 <= max ? max : AUTO;\r
383                                         delete this.boxSizingOffsetTB;\r
384                                 };\r
385                         } else {\r
386                                 this.boxWidth  = this.contentWidth  = allowW;\r
387                                 this.boxHeight = this.contentHeight = allowH;\r
388                                 delete this.minContentHeight;\r
389                                 delete this.maxContentHeight;\r
390                                 delete this.contentL;\r
391                                 delete this.contentT;\r
392                                 delete this.contentR;\r
393                                 delete this.contentB;\r
394                         };\r
395                 },\r
396                 \r
397                 /**\r
398                  * 要素の追加・削除\r
399                  * 1. ペイントがある // 予約のみ\r
400                  * 2. コンテンツがある // 予約のみ *\r
401                  * 3. コンテンツを削除 // 予約のみ\r
402                  * 4. 要素を削除 // 予約のみ\r
403                  * \r
404                  * コンテンツの再計算\r
405                  * 0. 要素追加して css セット\r
406                  * 1. コンテンツの変更\r
407                  * 2. font 指定の変更\r
408                  * 3. contentWidth の変更 (コンテンツの高さの再計算) 前回の contentWidth の保持\r
409                  * \r
410                  * contentSize, scrollSize の決定\r
411                  */\r
412                 _mesure : function( dirty ){\r
413                         var content = this._content,\r
414                                 root    = this.rootData,\r
415                                 style   = this.styleData,\r
416                                 w       = this.contentWidth,\r
417                                 h       = this.contentHeight;\r
418                         switch( this.updateContent === true ? X.Css.Dirty.CONTENT : dirty ){\r
419                                 case X.Css.Dirty.CONTENT : // コンテンツが変更された\r
420                                         this.paint( 0 );\r
421                                         this.lastContentWidth = -1;\r
422                                 case X.Css.Dirty.FONT   : // フォントサイズが変更された\r
423                                         this.commitStyle();\r
424                                 case X.Css.Dirty.REFLOW : // レイアウトの再計算が必要\r
425                                         /* http://web-designs.seesaa.net/article/188400668.html\r
426                                          * min-width の値が max-width の値より大きい場合は、max-width の値は min-width の値に設定される。\r
427                                          * \r
428                                          * テキストノードがあり\r
429                                          * 1. contentWidth === AUTO\r
430                                          *     style を更新して contentWidth の決定\r
431                                          *     min or max に引っかかったら style 更新\r
432                                          *     contentHeight === AUTO の場合\r
433                                          *     textHeight の決定\r
434                                          *     contentHeight !== AUTO の場合 scrollHeight のみ更新\r
435                                          * 2. contentHeight === AUTO かつ \r
436                                          *     コンテンツの高さの再取得が必要( contentWidth が最終計測時の contentWidth と一致 かつ フォント・コンテンツに変更無し の場合再取得不要)\r
437                                          *      style を更新して contentHeight の決定\r
438                                          *     必要でない\r
439                                          * 3. content のサイズがすでに決定している\r
440                                          *     コンテンツの高さの再取得が必要\r
441                                          *     必要でない\r
442                                          */   \r
443                                         if( this.rawText ){\r
444                                                 if( w === AUTO ){\r
445                                                         w = this.contentWidth = this.elm.offsetWidth;\r
446                                                         this.scrollWidth = w + this.contentL + this.contentR;\r
447                                                         if( this.maxContentWidth < w - this.boxSizingOffsetLR ) this.contentWidth = this.maxContentWidth + this.boxSizingOffsetLR;\r
448                                                         if( w - this.boxSizingOffsetLR < this.minContentWidth ) this.contentWidth = this.minContentWidth + this.boxSizingOffsetLR;\r
449                                                         this.lastContentWidth = this.contentWidth;\r
450                                                         \r
451                                                         w !== this.contentWidth && this.commitStyle();\r
452                                                         \r
453                                                         if( h === AUTO ){\r
454                                                                 h = this.conetntHeight = this.elm.offsetHeight;\r
455                                                                 this.scrollHeight = h + this.contentT + this.contentB;\r
456                                                                 if( this.maxContentHeight < h - this.boxSizingOffsetTB ) this.contentHeight = this.maxContentHeight + this.boxSizingOffsetTB;\r
457                                                                 if( h - this.boxSizingOffsetTB < this.minContentHeight ) this.contentHeight = this.minContentHeight + this.boxSizingOffsetTB;\r
458                                                         } else {\r
459                                                                 this.scrollHeight = this.elm.offsetHeight + this.contentT + this.contentB;\r
460                                                         };\r
461                                                 } else\r
462                                                 if( h === AUTO ){\r
463                                                         if( w !== this.lastContentWidth || dirty !== X.Css.Dirty.REFLOW ){\r
464                                                                 this.commitStyle();\r
465                                                                 this.lastContentWidth  = w;\r
466                                                                 h = this.conetntHeight = this.elm.offsetHeight;\r
467                                                                 this.scrollWidth       = w + this.contentL + this.contentR;\r
468                                                                 this.scrollHeight      = h + this.contentT + this.contentB;\r
469                                                                 if( this.maxContentHeight < h - this.boxSizingOffsetTB ) this.contentHeight = this.maxContentHeight + this.boxSizingOffsetTB;\r
470                                                                 if( h - this.boxSizingOffsetTB < this.minContentHeight ) this.contentHeight = this.minContentHeight + this.boxSizingOffsetTB;                                                           \r
471                                                         } else {\r
472                                                                 this.scrollWidth  = w + this.contentL + this.contentR;\r
473                                                                 this.scrollHeight = h + this.contentT + this.contentB;\r
474                                                                 root.paintReserve( this );\r
475                                                         };\r
476                                                 } else {\r
477                                                         if( dirty !== X.Css.Dirty.REFLOW ){\r
478                                                                 this.commitStyle();\r
479                                                                 this.scrollWidth  = this.elm.offsetWidth  + this.contentL + this.contentR;\r
480                                                                 this.scrollHeight = this.elm.offsetHeight + this.contentT + this.contentB;\r
481                                                         } else {\r
482                                                                 root.paintReserve( this );\r
483                                                                 this.scrollWidth  = w + this.contentL + this.contentR;\r
484                                                                 this.scrollHeight = h + this.contentT + this.contentB;\r
485                                                         };\r
486                                                 };                                      \r
487                                         } else {\r
488                                                 if( w === AUTO ) this.contentWidth  = w = 0 < this.minContentWidth  ? this.minContentWidth  : 0;\r
489                                                 if( h === AUTO ) this.contentHeight = h = 0 < this.minContentHeight ? this.minContentHeight : 0;\r
490                                                 this.scrollWidth  = w + this.contentL + this.contentR;\r
491                                                 this.scrollHeight = h + this.contentT + this.contentB;\r
492                                                 root.paintReserve( this );                              \r
493                                         };\r
494                                         break;                  \r
495                                 case X.Css.Dirty.PAINT : // 再描画のみ必要\r
496                                         root.paintReserve( this );\r
497                                         break;                                          \r
498                         };\r
499                 },\r
500                 /**\r
501                  * 自身のコンテンツサイズを元に AUTO な width, height を確定していく\r
502                  */\r
503                 postMesure : function(){\r
504                         var style = this.styleData,\r
505                                 styles, calc, box,\r
506                                 contentW, contentH,\r
507                                 contentSize, contentPlus,\r
508                                 paddingT, paddingR, paddingB, paddingL,\r
509                                 borderT, borderR, borderB, borderL,\r
510                                 min, max;\r
511                         if( style ){\r
512                                 styles   = style.data;\r
513                                 calc     = _AbstractUINode.advancedCalcValue;\r
514                                 contentW = this.contentWidth;\r
515                                 box      = styles[ X.Css.AttrNo.sizing ];\r
516                                 \r
517                                 // Width\r
518                                 if( this.boxWidth === AUTO ){\r
519                                         paddingR = calc( styles[ X.Css.AttrNo.padding + 1 ], contentW );                                        \r
520                                         paddingL = calc( styles[ X.Css.AttrNo.padding + 3 ], contentW );                                        \r
521                                         borderR  = styles[ X.Css.AttrNo.border + 1 ];                                   \r
522                                         borderL  = styles[ X.Css.AttrNo.border + 3 ];                                   \r
523                                         //marginR  = calc( styles[ X.Css.AttrNo.margin + 1 ], contentW );\r
524                                         //marginL  = calc( styles[ X.Css.AttrNo.margin + 3 ], contentW );\r
525                                         contentPlus = 0;\r
526                                         switch( box ){\r
527                                                 //case 3 : // margin-box\r
528                                                 //       contentPlus  = ( marginR + marginL );\r
529                                                 case 2 : // border-box\r
530                                                          contentPlus  = borderR + borderL;\r
531                                                 case 1 : // padding-box\r
532                                                          contentPlus += paddingR + paddingL;\r
533                                                 // case 0 : // content-box\r
534                                         };\r
535                                         contentW += contentPlus;\r
536                                         if( !style.constraintW ){\r
537                                                 min = styles[ X.Css.AttrNo.minWidth ];\r
538                                                 max = styles[ X.Css.AttrNo.maxWidth ];\r
539                                                 if( contentW < min && 1 <= min && contentPlus < min ){\r
540                                                         this.contentWidth = min - contentPlus;\r
541                                                 } else\r
542                                                 if( max < contentW && 1 <= max && contentPlus < max ){\r
543                                                         this.contentWidth = max - contentPlus;\r
544                                                 };\r
545                                         };\r
546                                         this.contentL = /* marginL + */ borderL + paddingL;\r
547                                         this.contentR = /* marginR + */ borderR + paddingR;\r
548                                         this.boxWidth = this.contentWidth + this.contentL + this.contentR;\r
549                                 };\r
550                                 // Height\r
551                                 if( this.boxHeight === AUTO ){\r
552                                         contentH    = this.contentHeight;\r
553                                         contentSize = styles[ X.Css.AttrNo.pageBox ] === true ? contentH : contentW;\r
554                                         paddingT    = calc( styles[ X.Css.AttrNo.padding + 0 ], contentSize );// paddingTRBL の % 指定は 最大幅に対して TB でも幅に対して\r
555                                         paddingB    = calc( styles[ X.Css.AttrNo.padding + 2 ], contentSize );\r
556                                         borderT     = styles[ X.Css.AttrNo.border + 0 ];\r
557                                         borderB     = styles[ X.Css.AttrNo.border + 2 ];\r
558                                         //marginT     = calc( styles[ X.Css.AttrNo.margin + 0 ], contentSize );// marginTRBL の % 指定は 最大幅に対して TB でも幅に対して\r
559                                         //marginB     = calc( styles[ X.Css.AttrNo.margin + 2 ], contentSize );\r
560                                         contentPlus = 0;\r
561                                         switch( box ){\r
562                                                 //case 3 : // margin-box\r
563                                                          //contentPlus  = ( marginT + marginB );\r
564                                                 case 2 : // border-box\r
565                                                          contentPlus  = borderT + borderB;\r
566                                                 case 1 : // padding-box\r
567                                                          contentPlus += paddingT + paddingB;\r
568                                                 // case 0 : // content-box\r
569                                         };\r
570                                         contentH += contentPlus;\r
571                                         if( !style.constraintH ){\r
572                                                 min = styles[ X.Css.AttrNo.minHeight ];\r
573                                                 max = styles[ X.Css.AttrNo.maxHeight ];\r
574                                                 if( contentH < min && 1 <= min && contentPlus < min ){\r
575                                                         this.contentHeight = min - contentPlus;\r
576                                                 } else\r
577                                                 if( max < contentH && 1 <= max && contentPlus < max ){\r
578                                                         this.contentHeight = max - contentPlus;\r
579                                                 };\r
580                                         };\r
581                                         this.contentT  = marginT + borderT + paddingT;\r
582                                         this.contentB  = marginB + borderB + paddingB;                                          \r
583                                         this.boxHeight = this.contentHeight + this.contentT + this.contentB;\r
584                                 };                              \r
585                         } else {\r
586                                 this.boxWidth  = this.contentWidth;\r
587                                 this.boxHeight = this.contentHeight;\r
588                                 delete this.minContentHeight;\r
589                                 delete this.maxContentHeight;\r
590                                 delete this.contentL;\r
591                                 delete this.contentT;\r
592                                 delete this.contentR;\r
593                                 delete this.contentB;\r
594                         };\r
595                 },\r
596                 \r
597                 listen : function( type, arg1, arg2, arg3 ){\r
598                         var root, events, counter;\r
599                         if( X.UI.Event._START_POINTER <= type && type <= X.UI.Event._END_POINTER ){\r
600                                 if( this.phase < 3 ){\r
601                                         if( !( events = this.reserveEvents ) ) this.reserveEvents = events = [];\r
602                                         events[ events.length ] = [ type, arg1, arg2, arg3 ];\r
603                                         return this;\r
604                                 };\r
605                                 if( X.UI.Event._START_XUI_EVENT < type && type < X.UI.Event._END_XUI_EVENT ){\r
606                                         if( !this.gesture ){\r
607                                                 this.gesture = new X.UI.Gesture( this.root, this, type );\r
608                                         } else {\r
609                                                 this.gesture.listen( type );\r
610                                         };\r
611                                 } else {\r
612                                         root    = this.rootData;\r
613                                         counter = root.eventCounter;\r
614                                         if( counter[ type ] ){\r
615                                                 ++counter[ type ];\r
616                                         } else {\r
617                                                 counter[ type ] = 1;                            \r
618                                                 root.elmMouseCatch.listen( X.UI.Event.IdToName[ type ], eventRellay );\r
619                                         };\r
620                                 };\r
621                         };\r
622                         if( typeof arg1 === 'function' ){\r
623                                 return X.EventDispatcher.prototype.listen.apply( this, [ type, this.User, arg1, arg2 ] );\r
624                         };\r
625                         return X.EventDispatcher.prototype.listen.apply( this, [ type, arg1 || this.User, arg2 || arg1, arg3 || arg2 ] );\r
626                 },\r
627                 unlisten : function( type, arg1, arg2, arg3 ){\r
628                         var root, events, i, ev, counter;\r
629                         if( X.UI.Event._START_POINTER <= type && type <= X.UI.Event._END_POINTER ){\r
630                                 if( this.phase < 3 ){\r
631                                         if( !( events = this.reserveEvents ) ) return this;\r
632                                         for( i = events.length; i; ){\r
633                                                 ev = events[ --i ];\r
634                                                 if( ev[ 0 ] === type && ev[ 1 ] === arg1 && ev[ 2 ] === arg2 ){\r
635                                                         events.split( i, 1 );\r
636                                                         return this;\r
637                                                 };\r
638                                         }; \r
639                                         return this;\r
640                                 };\r
641 \r
642                                 if( X.UI.Event._START_XUI_EVENT < type && type < X.UI.Event._END_XUI_EVENT ){\r
643                                         this.gesture && this.gesture.unlisten( type );\r
644                                 } else {\r
645                                         root    = this.rootData;\r
646                                         counter = root.eventCounter;\r
647                                         if( !counter[ type ] ) return this;\r
648                                         --counter[ type ];\r
649                                         if( counter[ type ] === 0 ){\r
650                                                 X.Dom.Event.remove( root.elmMouseCatch, X.UI.Event.IdToName[ type ], eventRellay );\r
651                                                 delete counter[ type ];\r
652                                         };\r
653                                 };\r
654                         };\r
655                         if( typeof arg1 === 'function' ){\r
656                                 return X.EventDispatcher.prototype.unlisten.apply( this, [ type, this.User, arg1, arg2 ] );\r
657                         };\r
658                         return X.EventDispatcher.prototype.unlisten.apply( this, [ type, arg1 || this.User, arg2 || arg1, arg3 || arg2 ] );\r
659                 },\r
660                 \r
661                 dispatch : function( e ){\r
662                         var xve  = X.UI.Event,\r
663                                 ret  = X.EventDispatcher.prototype.dispatch.call( this, e ),\r
664                                 type = e.type;\r
665                         if( ret & X.Callback.MONOPOLY && !this.hitChildData && ( xve._POINTER_MOVE === type || xve._MOUSE_MOVE === type || xve.FILE_DRAG === type ) ){\r
666                                 this.rootData.monopolyNodeData = this;\r
667                                 return ret;\r
668                         };\r
669                         this.rootData.monopolyNodeData = null;\r
670                         if( xve._START_BUBLEUP < type && this.parentData && ret & X.Callback.STOP_PROPAGATION === 0 && ret & X.Callback.STOP_NOW === 0 ) return this.parentData.dispatch( e );\r
671                         return ret;\r
672                 }\r
673                 \r
674         }\r
675 );\r
676 \r
677 _AbstractUINode.finalValue = function( styleValue, styleMin, styleMax, srcValue ){\r
678         var calc = _AbstractUINode.calcValue,\r
679                 v    = calc( styleValue, srcValue ),\r
680                 min  = calc( styleMin,   srcValue ),\r
681                 max  = calc( styleMax,   srcValue );\r
682         if( v < min ) return min;\r
683         if( max < v ) return max;\r
684         return v;\r
685 };\r
686 _AbstractUINode.calcValue = function( styleValue, srcValue ){\r
687         switch( styleValue ){\r
688                 case 0 :\r
689                         return 0;\r
690                 case AUTO :\r
691                         return AUTO;\r
692                 case FULL :\r
693                         return srcValue; // 100%\r
694         };\r
695         if( 1 <= styleValue ) return styleValue; // legth\r
696         if( -1 < styleValue ) return FLOOR( srcValue * styleValue ); // %       \r
697         return styleValue; // - length\r
698 };\r
699 _AbstractUINode.advancedCalcValue = function( styleValue, srcValue ){\r
700         switch( styleValue ){\r
701                 case 0 :\r
702                         return 0;\r
703                 case AUTO :\r
704                         return srcValue;\r
705                 case FULL :\r
706                         //throw new Error( 'advancedCalcValue FULL' ); \r
707                         // return ; // 100%\r
708         };\r
709         if( 1 <= styleValue ) return styleValue; \r
710         if( -1 < styleValue ) return FLOOR( ( srcValue / ( 1 - styleValue ) ) * styleValue ); // %      \r
711         return styleValue; // - length\r
712 };\r
713 \r
714 \r
715 var AbstractUINode = X.Class.create(\r
716         'AbstractUINode',\r
717         X.Class.ABSTRACT | X.Class.SUPER_ACCESS,\r
718         {\r
719                 style : null,\r
720                 parent : function(){\r
721                         return X.Class._getPrivate( this ).parent;\r
722                 },\r
723                 root : function(){\r
724                         return X.Class._getPrivate( this ).root;\r
725                 },\r
726                 listen : function( type, arg1, arg2, arg3 ){\r
727                         X.Class._getPrivate( this ).listen( type, arg1, arg2, arg3 );\r
728                         return this;\r
729                 },\r
730                 listenOnce : function( type, arg1, arg2, arg3 ){\r
731                         X.Class._getPrivate( this ).listenOnce( type, arg1, arg2, arg3 );\r
732                         return this;\r
733                 },\r
734                 unlisten : function( type, arg1, arg2, arg3 ){\r
735                         X.Class._getPrivate( this ).unlisten( type, arg1, arg2, arg3 );\r
736                         return this;\r
737                 },\r
738                 getNextNode : function(){\r
739                         \r
740                 },\r
741                 getPrevNode : function(){\r
742                         \r
743                 },\r
744                 dispatch : function( e ){\r
745                         return X.Class._getPrivate( this ).dispatch( e );\r
746                 },\r
747                 nodeIndex : function( v ){\r
748                         var data = X.Class._getPrivate( this );\r
749                         if( typeof v === 'number' ){\r
750                                 // data.nodeIndex( v );\r
751                                 return this;\r
752                         };\r
753                         return data.parentData ? data.parentData.nodes.indexOf( data ) : 0;\r
754                 },\r
755                 displayIndex : function(){\r
756                         \r
757                 },\r
758                 // ちゃんとやれば不要!\r
759                 mesure : function(){\r
760                         var data = X.Class._getPrivate( this );\r
761                         data.mesure();\r
762                         4 <= data.phase && data.rootData.reserveCalc();\r
763                         return this;\r
764                 },\r
765                 getX : function(){\r
766                         // dirty の場合、rootData.calculate\r
767                         return X.Class._getPrivate( this ).x;\r
768                 },\r
769                 getY : function(){\r
770                         // dirty の場合、rootData.calculate\r
771                         return X.Class._getPrivate( this ).y;\r
772                 },\r
773                 getAbsoluteX : function(){\r
774                         // dirty の場合、rootData.calculate\r
775                         return X.Class._getPrivate( this ).absoluteX;\r
776                 },\r
777                 getAbsoluteY: function(){\r
778                         // dirty の場合、rootData.calculate\r
779                         return X.Class._getPrivate( this ).absoluteY;\r
780                 },\r
781                 getWidth : function(){\r
782                         // dirty の場合、rootData.calculate\r
783                         return X.Class._getPrivate( this ).w;\r
784                 },\r
785                 getHeight : function(){\r
786                         // dirty の場合、rootData.calculate\r
787                         return X.Class._getPrivate( this ).h;\r
788                 },\r
789                 scrollTo : function( x, y ){\r
790                         X.Class._getPrivate( this ).scrollTo( x, y );\r
791                 },\r
792                 getScrollX : function( v ){\r
793                         // dirty の場合、rootData.calculate\r
794                         return X.Class._getPrivate( this ).scrollX( v );\r
795                 },\r
796                 getScrollY : function( v ){\r
797                         // dirty の場合、rootData.calculate\r
798                         return X.Class._getPrivate( this ).scrollY( v );\r
799                 },\r
800                 disabled : function( v ){\r
801                         return X.Class._getPrivate( this ).disabled( v );\r
802                 },\r
803                 cursor : function( v ){\r
804                         return X.Class._getPrivate( this ).cursor( v );\r
805                 }\r
806         }\r
807 );