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