handler: bug fix (handler activation)
[platform/framework/web/web-ui-fw.git] / src / widgets / handler / js / jquery.tizen.scrollview.handler.js
1 /* ***************************************************************************
2  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  * ***************************************************************************
22  *
23  * Authors: Wonseop Kim ( wonseop.kim@samsung.com )
24 */
25
26 /**
27  * "Handler" is a widget helping a user to scroll a window or panel.
28  * It is different from the scrollview feature in that the handler has a fixed size
29  * and disappears when a scroll size is smaller than a parent window's size.
30  * If the handler widget is activated, a scroll bar on the screen will be deactivated.
31  * The handler widget supports scrolling up and down and indicates the position of the scrolled window.
32  *
33  * HTML Attributes:
34  *
35  *              data-handler : This attribute is indicating that whether enable.
36  *                                              If you want to use, you will set 'true'.
37  *              data-handler-theme : Set the widget theme ( optional )
38  *
39  * APIs:
40  *
41  *              enableHandler ( boolean )
42  *                      : Get or set the use of handler widget.
43  *                      If the value is "true", it will be run handler widget.
44  *                      If the value is "false", it will be not run handler widget.
45  *                      If no value is specified, will act as a getter.
46  *
47  * Events:
48  *
49  * Examples:
50  *
51  *              <div data-role="content" data-scroll="y" data-handler="true">
52  *                      <ul data-role="listview">
53  *                              <li data-role="list-divider">A</li>
54  *                              <li><a href="#">Adam Kinkaid</a></li>
55  *                                      ...
56  *                      </ul>
57  *              </div>
58  */
59
60 /**
61         @class handler
62         The handler widget enables the user to vertically scroll through a page or panel using a fixed-size handle. The widget indicates the position of the scrolled window, and only appears on the screen if the parent page or panel's scroll size is larger than the screen size. <br/> To add a handler widget to the application, use the following code:
63
64                 <div data-role="content" data-scroll="y" data-handler="true">
65                         <ul data-role="listview">
66                                 <li data-role="list-divider">A</li>
67                                 <li><a href="#">Adam Kinkaid</a></li>
68                                         ...
69                         </ul>
70                 </div>
71         
72         You can use the enableHandler method with the handler widget to get (if no value is defined) or set the handler usage status. If the [enable] value is true, the handler is enabled; otherwise the handler is not used.
73
74                 $("#.selector").scrollview("enableHandler", [enable]);
75 */
76 /**
77         @property {Boolean} data-handler
78         Enables the handler widget. The value must be set to true.
79 */
80 /**
81         @property {String} data-handler-theme
82         Sets the handler widget theme.
83 */
84 ( function ( $, document, undefined ) {
85         // The options of handler in scrollview
86         $.tizen.scrollview.prototype.options.handler = false;
87         $.tizen.scrollview.prototype.options.handlerTheme = "s";
88
89         var originSetOption = $.tizen.scrollview.prototype._setOption,
90                 createHandler = function ( target ) {
91                         var $view = target,
92                                 prefix = "<div class=\"ui-handler ui-handler-direction-",
93                                 suffix = "\"><div class=\"ui-handler-track\"><div class=\"ui-handler-thumb\"></div></div></div>",
94                                 scrollview = $view.data( "scrollview" ),
95                                 options = scrollview.options,
96                                 direction = options.direction,
97                                 parentTheme = $.mobile.getInheritedTheme( scrollview, "s" ),
98                                 theme = options.theme || parentTheme,
99                                 isHorizontal = ( scrollview.options.direction === "x" ),
100                                 _$view = scrollview._$view,
101                                 _$clip = scrollview._$clip,
102                                 handler = null,
103                                 handlerThumb = null,
104                                 viewLength = 0,
105                                 clipLength = 0,
106                                 handlerHeight = 0,
107                                 handlerMargin = 0,
108                                 trackLength = 0,
109                                 moveTimer,
110                                 isTouchable = $.support.touch,
111                                 dragStartEvt = ( isTouchable ? "touchstart" : "mousedown" ) + ".handler",
112                                 dragMoveEvt = ( isTouchable ? "touchmove" : "mousemove" ) + ".handler",
113                                 dragStopEvt = ( isTouchable ? "touchend" : "mouseup" ) + ".handler",
114                                 dragLeaveEvt = ( isTouchable ? " touchleave" : " mouseleave" ) + ".handler",
115                                 calculateLength = function () {
116                                         clipLength = ( isHorizontal ? _$clip.width() : _$clip.height() );
117                                         viewLength = ( isHorizontal ? _$view.width() : _$view.height() ) - clipLength;
118                                         trackLength = clipLength - handlerHeight - handlerMargin * 2;
119                                 },
120                                 setHanderPostion = function ( scrollPos ) {
121                                         var handlerPos = Math.round( ( isHorizontal ? scrollPos.x : scrollPos.y ) / viewLength * trackLength );
122                                         handlerThumb[0].style[ ( isHorizontal ? "left" : "top" ) ] = handlerPos + "px";
123                                 },
124                                 stopHandlerScroll = function () {
125                                         $( document ).unbind( ".handler" );
126                                         $view.moveData = null;
127                                         _$view.trigger( "scrollstop" );
128                                 };
129
130                         if ( $view.find( ".ui-handler-thumb" ).length !== 0 || typeof direction !== "string" ) {
131                                 return;
132                         }
133
134                         $view.addClass( " ui-handler-" + theme ).append( [ prefix, direction, suffix ].join( "" ) );
135                         handler = $view.find( ".ui-handler" );
136                         handlerThumb = $view.find( ".ui-handler-thumb" ).hide();
137                         handlerHeight = ( isHorizontal ? handlerThumb.width() : handlerThumb.height() );
138                         handlerMargin = ( isHorizontal ? parseInt( handler.css( "right" ), 10 ) : parseInt( handler.css( "bottom" ), 10 ) );
139
140                         $.extend( $view, {
141                                 moveData : null
142                         });
143
144                         // handler drag
145                         handlerThumb.bind( dragStartEvt, {
146                                 e : handlerThumb[0]
147                         }, function ( event ) {
148                                 scrollview._stopMScroll();
149
150                                 var target = event.data.e,
151                                         t = ( isTouchable ? event.originalEvent.targetTouches[0] : event );
152
153                                 target.style.opacity = 1.0;
154
155                                 $view.moveData = {
156                                         target : target,
157                                         X : parseInt( target.style.left, 10 ) || 0,
158                                         Y : parseInt( target.style.top, 10 ) || 0,
159                                         pX : t.pageX,
160                                         pY : t.pageY
161                                 };
162                                 calculateLength();
163
164                                 _$view.trigger( "scrollstart" );
165
166                                 if ( !isTouchable ) {
167                                         event.preventDefault();
168                                 }
169
170                                 $( document ).bind( dragMoveEvt, function ( event ) {
171                                         var moveData = $view.moveData,
172                                                 target = moveData.target,
173                                                 handlePos = 0,
174                                                 scrollPos = 0,
175                                                 t = ( isTouchable ? event.originalEvent.targetTouches[0] : event );
176
177                                         handlePos = ( isHorizontal ? moveData.X + t.pageX - moveData.pX : moveData.Y + t.pageY - moveData.pY );
178
179                                         if ( handlePos < 0 ) {
180                                                 handlePos = 0;
181                                         }
182
183                                         if ( handlePos > trackLength ) {
184                                                 handlePos = trackLength;
185                                         }
186                                         scrollPos = - Math.round( handlePos / trackLength * viewLength );
187
188                                         if ( isHorizontal ) {
189                                                 scrollview._setScrollPosition( scrollPos, 0 );
190                                                 target.style.left = handlePos + "px";
191                                         } else {
192                                                 scrollview._setScrollPosition( 0, scrollPos );
193                                                 target.style.top = handlePos + "px";
194                                         }
195
196                                         event.preventDefault();
197                                 }).bind( dragStopEvt + dragLeaveEvt, function ( event ) {
198                                         stopHandlerScroll();
199                                 });
200                         });
201
202                         _$view.bind( dragStopEvt, function ( event ) {
203                                 stopHandlerScroll();
204                         });
205
206                         $view.bind( "scrollstart", function ( event ) {
207                                 if ( !scrollview.enableHandler() ) {
208                                         return;
209                                 }
210                                 calculateLength();
211
212                                 if ( moveTimer ) {
213                                         clearInterval( moveTimer );
214                                         moveTimer = undefined;
215                                 }
216
217                                 if ( viewLength < 0 || clipLength < handlerHeight ) {
218                                         return;
219                                 }
220
221                                 handlerThumb.addClass( "ui-handler-visible" )
222                                                         .stop( true, true )
223                                                         .fadeIn( 'fast' );
224                         }).bind( "scrollupdate", function ( event, data ) {
225                                 if ( !scrollview.enableHandler() || viewLength < 0 || clipLength < handlerHeight ) {
226                                         return;
227                                 }
228
229                                 setHanderPostion( scrollview.getScrollPosition() );
230                         }).bind( "scrollstop", function ( event ) {
231                                 if ( !scrollview.enableHandler() || viewLength < 0 ) {
232                                         return;
233                                 }
234
235                                 moveTimer = setInterval( function () {
236                                         setHanderPostion( scrollview.getScrollPosition() );
237                                         if ( !scrollview._gesture_timer ) {
238                                                 clearInterval( moveTimer );
239                                                 moveTimer = undefined;
240                                         }
241                                 }, 10 );
242
243                                 if ( scrollview._handlerTimer ) {
244                                         clearTimeout( scrollview._handlerTimer );
245                                         scrollview._handlerTimer = 0;
246                                 }
247                                 scrollview._handlerTimer = setTimeout( function () {
248                                         if ( scrollview._timerID === 0 && $view.moveData === null ) {
249                                                 handlerThumb.removeClass( "ui-handler-visible" )
250                                                                         .stop( true, true )
251                                                                         .css( "opacity", 1.0 )
252                                                                         .fadeOut( 'fast' );
253                                                 scrollview._handlerTimer = 0;
254                                         }
255                                 }, 1000 );
256                         }).bind( "mousewheel", function ( event ) {
257                                 handlerThumb.removeClass( "ui-handler-visible" ).hide();
258                                 setHanderPostion( scrollview.getScrollPosition() );
259                         });
260                 };
261
262         $.extend( $.tizen.scrollview.prototype, {
263                 enableHandler: function ( enabled ) {
264                         if ( typeof enabled === 'undefined' ) {
265                                 return this.options.handler;
266                         }
267
268                         this.options.handler = !!enabled;
269
270                         var $view = this.element;
271                         if ( this.options.handler ) {
272                                 if ( $view.find( ".ui-handler" ).length === 0 ) {
273                                         createHandler( $view );
274                                 }
275
276                                 $view.find( ".ui-scrollbar" ).hide();
277                                 $view.find( ".ui-handler" ).show();
278                         } else {
279                                 $view.find( ".ui-handler" ).hide();
280                                 $view.find( ".ui-scrollbar" ).show();
281                         }
282                 },
283
284                 _setHandlerTheme: function ( handlerTheme ) {
285                         if ( !handlerTheme ) {
286                                 return;
287                         }
288
289                         var oldClass = "ui-handler-" + this.options.handlerTheme,
290                                 newClass = "ui-handler-" + handlerTheme;
291
292                         this.element.removeClass( oldClass ).addClass( newClass );
293                         this.options.handlerTheme = handlerTheme;
294                 },
295
296                 _setOption: function ( key, value ) {
297                         switch ( key ) {
298                         case "handler":
299                                 this.enableHandler( value );
300                                 break;
301                         case "handlerTheme":
302                                 this._setHandlerTheme( value );
303                                 break;
304                         default:
305                                 originSetOption.call( this, key, value );
306                         }
307                 },
308
309                 _handlerTimer : 0
310         });
311
312         $( document ).delegate( ":jqmData(scroll)", "scrollviewcreate", function () {
313                 var widget = $( this );
314                 if ( widget.attr( "data-" + $.mobile.ns + "scroll" ) === "none"
315                                 || widget.attr( "data-" + $.mobile.ns + "handler" ) !== "true" ) {
316                         return;
317                 }
318                 widget.scrollview( "enableHandler", "true" );
319         });
320 } ( jQuery, document ) );