OSDN Git Service

Fix the bug of X.NodeAnime.
[pettanr/clientJs.git] / 0.6.x / js / 20_ui / 20_Root.js
1 var XUI_rootData         = null,
2         XUI_xnodeIneraction  = null,
3         XUI_mousemoveFix     = X_UA[ 'WinPhone' ] && X_UA[ 'IE9' ],
4         XUI_mousemoveFixOn   = 0,
5         XUI_mousemoveFixX    = 0,
6         XUI_mousemoveFixY    = 0,
7         XUI_mousemoveFixLast = null,
8         XUI_UINODES_HOVER    = [],
9         XUI_EVENT_COUNTER    = {},
10         XUI_uinodeTarget     = null,
11         XUI_xnodeInteractionOverlay,
12         XUI_interactionBusy  = false;
13
14 function XUI_mousemoveFixResetScroll(){
15         var raw = XUI_xnodeInteractionOverlay[ '_rawObject' ];
16
17         if( XUI_mousemoveFix ){
18                 XUI_mousemoveFixX = raw.scrollLeft = raw.offsetWidth;
19                 XUI_mousemoveFixY = raw.scrollTop  = raw.offsetHeight;          
20         };
21 };
22
23 function XUI_mousemoveFixScrollEnd(){
24         var raw  = XUI_xnodeInteractionOverlay[ '_rawObject' ];
25
26         XUI_mousemoveFixOn = 0;
27         XUI_mousemoveFixLast.type = 'pointerup';
28         X_UI_eventRellay( XUI_mousemoveFixLast );
29         
30         raw.scrollLeft = XUI_mousemoveFixX;
31         raw.scrollTop  = XUI_mousemoveFixY;
32 };
33
34 function X_UI_eventRellay( e ){
35         var font    = X_ViewPort_baseFontSize,
36                 x       = e.pageX, // clientX は iOS4- で通らない?
37                 y       = e.pageY,
38                 type    = XUI_Event.NameToID[ e.type ],
39                 i       = 0,
40                 data    = XUI_rootData,
41                 sysOnly = false,
42                 ret     = X_CALLBACK_NONE,
43                 list    = XUI_UINODES_HOVER,
44                 raw, parent, _ret, eventIn, eventOut;
45
46         // mouseup で alert を出すと mouseleave が発生、ということでイベント中のイベント発火を禁止
47         if( XUI_interactionBusy ) return ret;
48         
49         XUI_interactionBusy = true;
50
51         if( XUI_mousemoveFix ){
52                 if( e.type === 'scroll' ){
53                         raw  = XUI_xnodeInteractionOverlay[ '_rawObject' ];
54                         type = XUI_mousemoveFixOn ? XUI_Event._POINTER_MOVE : XUI_Event._POINTER_DOWN;
55                         x    = XUI_mousemoveFixX - raw.scrollLeft;
56                         y    = XUI_mousemoveFixY - raw.scrollTop;
57                         e.pageX = x;
58                         e.pageY = y;
59                         e[ 'button' ]      = 0;
60                         e[ 'timestamp' ]   = e[ 'timeStamp' ];
61                         e[ 'pointerId' ]   = 1;
62                         e[ 'pointerType' ] = 'mouse';
63
64                         XUI_mousemoveFixOn && X_Timer_remove( XUI_mousemoveFixOn );
65                         XUI_mousemoveFixOn   = X_Timer_once( 250, XUI_mousemoveFixScrollEnd );
66                         XUI_mousemoveFixLast = X_Object_copy( e );
67                 };
68         };
69
70         e = X_Object_copy( e );
71         e.type = type;
72
73         // capture は pointer 毎に!
74         data.capcher( x / font, y / font );
75         data = XUI_uinodeTarget || data;
76
77         while( data ){
78                 _ret = data[ 'dispatch' ]( e, sysOnly ) || X_CALLBACK_NONE;
79                 ret |= _ret;
80                 if( type < XUI_Event._START_BUBLEUP || ret & X_CALLBACK_STOP_PROPAGATION ){
81                         break;
82                 };
83                 data = data.parentData;
84         };
85
86         for( i = list.length; i; ){
87                 parent = data = list[ --i ];
88                 while( parent.parentData && parent === parent.parentData.hitChildData ){
89                         parent = parent.parentData;
90                 };
91                 if( parent !== XUI_rootData ){
92                         if( data[ '_listeners' ] && data[ '_listeners' ][ XUI_Event.POINTER_OUT ] ){
93                                 if( !eventOut ){
94                                         eventOut = X_Object_copy( e );
95                                         eventOut.type = XUI_Event.POINTER_OUT;                                  
96                                 };
97                                 data[ 'dispatch' ]( eventOut, false );
98                         };
99                         delete data.hovering;
100                         list.splice( i, 1 );
101                 } else
102                 if( !data.hovering ){
103                         if( data[ '_listeners' ] && data[ '_listeners' ][ XUI_Event.POINTER_IN ] ){
104                                 if( !eventIn ){
105                                         eventIn = X_Object_copy( e );
106                                         eventIn.type = XUI_Event.POINTER_IN;                            
107                                 };
108                                 data[ 'dispatch' ]( eventIn, true );
109                         };
110                         data.hovering = true;
111                 };
112         };
113         XUI_interactionBusy = false;
114         return ret | X_CALLBACK_PREVENT_DEFAULT;
115 };
116
117 function X_UI_onMouseOut( e ){
118         var list = XUI_UINODES_HOVER,
119                 i = list.length, data;
120         console.log( 'pointer out!!' + e.type + i + ' ' + e.pointerType );
121
122         e = X_Object_copy( e );
123         e.type = XUI_Event.POINTER_OUT;
124         
125         for( ; i; ){
126                 data = list[ --i ];
127                 data[ '_listeners' ] && data[ '_listeners' ][ XUI_Event.POINTER_OUT ] && data[ 'dispatch' ]( e, false ); // new Event
128                 delete data.hovering;
129         };
130         list.length = 0;
131 };
132
133 /*
134  * body が存在したら要素を作成、css も指定
135  * 背景画像を読み終える onload で活動開始
136  */
137
138 var XUI_Root = XUI_Box.inherits(
139         '_Root',
140         X_Class.FINAL,
141         {
142                 layout                : XUI_Layout_Canvas,
143                 
144                 calcReserved          : false,
145                 
146                 cursorStyle           : null,
147                 
148                 Constructor : function( user, layout, args ){
149                         this[ 'Super' ]( user, layout, args );
150                         
151                         if( X_ViewPort_readyState === X_EVENT_XDOM_READY ){
152                                 X_Timer_once( 0, this, this.start );
153                         } else {
154                                 X_ViewPort[ 'listenOnce' ]( X_EVENT_XDOM_READY, this, this.start );
155                         };
156                         
157                         XUI_rootData = this;
158                 },
159                 
160                 start : function(){
161                         this.initialize( this.User, this, null, null );
162                         X_Timer_once( 0, this, this.addToView );
163                 },
164                 addToView : function(){
165                         // XUI_xnodeInteractionOverlay の前に追加する!
166                         this.addToParent( X_Node_body );
167
168                         XUI_xnodeInteractionOverlay = X_Node_body.create( 'div', {
169                                 'class'      : XUI_mousemoveFix ? 'mouse-operation-catcher-scrollFix' : 'mouse-operation-catcher',
170                                 unselectable : 'on'
171                         } );
172                         
173                         X_Node_body[ 'listen' ]( 'pointerleave', this, X_UI_onMouseOut );
174                         
175                         // hover や rollover rollout のための move イベントの追加
176                         // TODO この切り替えを ViewPort へ
177                         XUI_xnodeIneraction = ( X_UA[ 'IE' ] < 9 ? X_ViewPort_document : X_UA[ 'Opera' ] < 8 ? X_Node_body : X_ViewPort );
178                         
179                         if( XUI_mousemoveFix ){
180                                 XUI_xnodeInteractionOverlay[ 'listen' ]( [ 'scroll', 'mouseup' ], X_UI_eventRellay )[ 'create' ]( 'div' );
181                         } else {
182                                 XUI_xnodeIneraction[ 'listen' ]( 'pointermove', X_UI_eventRellay );
183                         };
184                         
185                         if( XUI_EVENT_COUNTER[ XUI_Event._POINTER_MOVE ] ){
186                                 ++XUI_EVENT_COUNTER[ XUI_Event._POINTER_MOVE ];
187                         } else {
188                                 XUI_EVENT_COUNTER[ XUI_Event._POINTER_MOVE ] = 1;
189                         };
190
191                         X_Timer_once( 0, this, this.afterAddToView );
192                 },
193                 afterAddToView : function(){
194                         this.xnode[ 'className' ]( 'Root' );
195                         
196                         this.creationComplete();
197                         X_Timer_once( 0, this, XUI_Root_do1stCalculate );
198                 },
199                 
200                 reserveCalc : function(){
201                         if( !this.calcReserved ){
202                                 this.calcReserved = true;
203                                 X_Timer_once( 0, this, this.calculate );
204                         };
205                 },
206                 calculate : function( e ){
207                         var cancelable = !e || ( e.type !== X_EVENT_VIEW_RESIZED && e.type !== X_EVENT_BASE_FONT_RESIZED ),
208                                 size, font, w, h;
209                         
210                         if( ( this[ 'dispatch' ]( { type : XUI_Event.LAYOUT_BEFORE, 'cancelable' : cancelable } ) & X_CALLBACK_PREVENT_DEFAULT ) && cancelable ){
211                                 console.log( 'Layout のキャンセル' );
212                                 return X_CALLBACK_NONE;
213                         };
214                         
215                         console.log( 'レイアウト開始' );
216                         
217                         XUI_mousemoveFix && XUI_mousemoveFixResetScroll();
218                         
219                         size = X[ 'ViewPort' ][ 'getSize' ]();
220                         font = X[ 'ViewPort' ][ 'getBaseFontSize' ]();
221                         this.layout.calculate( this, false, 0, 0, size[ 0 ] / font, size[ 1 ] / font );
222                         this.updateLayout();
223                         
224                         this.calcReserved = false;
225
226                         // size を測りながらレイアウトする結果、アップデートがない場合がある
227                         if( X_Node_updateTimerID ){
228                                 X_ViewPort[ 'listenOnce' ]( X_EVENT_AFTER_UPDATE, this, XUI_Root_onViewUpdate );
229                         } else {
230                                 this[ 'asyncDispatch' ]( XUI_Event.LAYOUT_COMPLETE );
231                         };
232
233                         return X_CALLBACK_NONE;
234                 },
235                 
236                 updateCoursor : function( cursor ){
237                         
238                 }
239         }
240 );
241
242 function XUI_Root_do1stCalculate(){
243         this.calculate();
244         this.phase = 4;
245         X_ViewPort
246                 [ 'listen' ]( X_EVENT_VIEW_RESIZED, this, this.calculate )
247                 [ 'listen' ]( X_EVENT_BASE_FONT_RESIZED, this, this.calculate );
248 };
249
250 function XUI_Root_onViewUpdate( e ){
251         console.log( 'レイアウト完了' );
252         this[ 'dispatch' ]( XUI_Event.LAYOUT_COMPLETE );
253 };
254
255 //var XUI_Root;
256 // TODO singleton
257 X.UI.Root = X.UI.Box.inherits(
258         'Root',
259         X_Class.NONE,
260         {
261                 Constructor : function(){
262                         var supports;
263                         
264                         //if( !XUI_Root ){
265                                 supports = XUI_Attr_createAttrDef( XUI_Box.prototype.usableAttrs, XUI_Layout_Canvas.overrideAttrsForSelf );
266                                 
267                                 //XUI_Root.prototype.layout       = XUI_Layout_Canvas;
268                                 XUI_Root.prototype.usableAttrs = supports;
269                                 XUI_Root.prototype.attrClass    = XUI_Attr_preset( XUI_Box.prototype.attrClass, supports, {
270                                                                         width  : '100%',
271                                                                         height : '100%'
272                                                                 } );
273                         //};
274                         X_Pair_create( this, XUI_Root( this, XUI_Layout_Canvas, arguments ) );
275                 }
276         });
277 /*
278 X.UI.Root = X.UI.Box.presets(
279         'Root',
280         XUI_Root,
281         {
282                 width  : '100%',
283                 height : '100%'
284         }
285 );*/
286