Export 0.2.1
[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-",
93                                 suffix = "\"><div class=\"ui-handler-track\"><div class=\"ui-handler-thumb\"></div></div></div>",
94                                 scrollview = $view.data( "scrollview" ),
95                                 direction = scrollview.options.direction,
96                                 isHorizontal = ( scrollview.options.direction === "x" ),
97                                 _$view = scrollview._$view,
98                                 _$clip = scrollview._$clip,
99                                 handler = null,
100                                 handlerThumb = null,
101                                 viewLength = 0,
102                                 clipLength = 0,
103                                 handlerHeight = 0,
104                                 handlerMargin = 0,
105                                 trackLength = 0,
106                                 isTouchable = $.support.touch,
107                                 dragStartEvt = ( isTouchable ? "touchstart" : "mousedown" ) + ".handler",
108                                 dragMoveEvt = ( isTouchable ? "touchmove" : "mousemove" ) + ".handler",
109                                 dragStopEvt = ( isTouchable ? "touchend" : "mouseup" ) + ".handler",
110                                 calculateLength = function () {
111                                         clipLength = ( isHorizontal ? _$clip.width() : _$clip.height() );
112                                         viewLength = ( isHorizontal ? _$view.outerWidth( true ) : _$view.outerHeight( true ) ) - clipLength;
113                                         trackLength = clipLength - handlerHeight - handlerMargin * 2;
114                                 },
115                                 setHanderPostion = function ( scrollPos ) {
116                                         var handlerPos = Math.round( ( isHorizontal ? scrollPos.x : scrollPos.y ) / viewLength * trackLength );
117                                         handlerThumb.css( isHorizontal ? "left" : "top", handlerPos );
118                                 };
119
120                         if ( $view.find( ".ui-handler-thumb" ).length !== 0 || typeof direction !== "string" ) {
121                                 return;
122                         }
123
124                         $view.append( prefix + direction + suffix );
125                         handler = $view.find( ".ui-handler" );
126                         handlerThumb = $view.find( ".ui-handler-thumb" ).hide();
127                         handlerHeight = ( isHorizontal ? handlerThumb.width() : handlerThumb.height() );
128                         handlerMargin = ( isHorizontal ? parseInt( handler.css( "right" ), 10 ) : parseInt( handler.css( "bottom" ), 10 ) );
129
130                         scrollview.enableHandler( scrollview.options.handler );
131
132                         $.extend( $view, {
133                                 moveData : null
134                         });
135
136                         // handler drag
137                         handlerThumb.bind( dragStartEvt, {
138                                 e : handlerThumb
139                         }, function ( event ) {
140                                 scrollview._stopMScroll();
141
142                                 var target = event.data.e,
143                                         t = ( isTouchable ? event.originalEvent.targetTouches[0] : event );
144
145                                 target.css( "opacity", 1.0 );
146
147                                 $view.moveData = {
148                                         target : target,
149                                         X : parseInt( target.css( 'left' ), 10 ) || 0,
150                                         Y : parseInt( target.css( 'top' ), 10 ) || 0,
151                                         pX : t.pageX,
152                                         pY : t.pageY
153                                 };
154                                 calculateLength();
155
156                                 _$view.trigger( "scrollstart" );
157                                 event.preventDefault();
158                                 event.stopPropagation();
159
160                                 $( document ).bind( dragMoveEvt, function ( event ) {
161                                         var moveData = $view.moveData,
162                                                 handlePos = 0,
163                                                 scrollPos = 0,
164                                                 t = ( isTouchable ? event.originalEvent.targetTouches[0] : event );
165
166                                         handlePos = ( isHorizontal ? moveData.X + t.pageX - moveData.pX : moveData.Y + t.pageY - moveData.pY );
167
168                                         if ( handlePos < 0 ) {
169                                                 handlePos = 0;
170                                         }
171
172                                         if ( handlePos > trackLength ) {
173                                                 handlePos = trackLength;
174                                         }
175                                         scrollPos = - Math.round( handlePos / trackLength * viewLength );
176
177                                         $view.attr( "display", "none" );
178                                         if ( isHorizontal ) {
179                                                 scrollview._setScrollPosition( scrollPos, 0 );
180                                                 moveData.target.css( {
181                                                         left : handlePos
182                                                 });
183                                         } else {
184                                                 scrollview._setScrollPosition( 0, scrollPos );
185                                                 moveData.target.css( {
186                                                         top : handlePos
187                                                 });
188                                         }
189                                         $view.attr( "display", "inline" );
190
191                                         event.preventDefault();
192                                         event.stopPropagation();
193                                 }).bind( dragStopEvt, function ( event ) {
194                                         $( document ).unbind( dragMoveEvt ).unbind( dragStopEvt );
195
196                                         $view.moveData = null;
197                                         _$view.trigger( "scrollstop" );
198
199                                         event.preventDefault();
200                                 });
201                         });
202
203                         $( document ).bind( dragMoveEvt, function ( event ) {
204                                 var isVisible = false,
205                                         vclass = "ui-scrollbar-visible";
206
207                                 if ( scrollview._$vScrollBar ) {
208                                         isVisible = scrollview._$vScrollBar.hasClass( vclass );
209                                 } else if ( scrollview._$hScrollBar ) {
210                                         isVisible = scrollview._$hScrollBar.hasClass( vclass );
211                                 }
212
213                                 if ( isVisible || $view.moveData !== null ) {
214                                         if ( handlerThumb.hasClass( "ui-handler-visible" ) ) {
215                                                 _$view.trigger( "scrollupdate" );
216                                         } else {
217                                                 _$view.trigger( "scrollstop" );
218                                         }
219                                 }
220                         }).bind( dragStopEvt, function ( event ) {
221                                 if ( handlerThumb.hasClass( "ui-handler-visible" ) ) {
222                                         _$view.trigger( "scrollstop" );
223                                 }
224                         });
225
226                         $view.bind( "scrollstart", function ( event ) {
227                                 if ( !scrollview.enableHandler() ) {
228                                         return;
229                                 }
230                                 calculateLength();
231
232                                 if ( clipLength > viewLength || trackLength < ( handlerHeight * 4 / 3 ) ) {
233                                         return;
234                                 }
235
236                                 handlerThumb.addClass( "ui-handler-visible" )
237                                                         .stop( true, true )
238                                                         .fadeIn( 'fast' );
239
240                                 event.preventDefault();
241                                 event.stopPropagation();
242                         }).bind( "scrollupdate", function ( event, data ) {
243                                 if ( !scrollview.enableHandler() || clipLength > viewLength || trackLength < ( handlerHeight * 4 / 3 ) ) {
244                                         return;
245                                 }
246
247                                 setHanderPostion( scrollview.getScrollPosition() );
248
249                                 event.preventDefault();
250                                 event.stopPropagation();
251                         }).bind( "scrollstop", function ( event ) {
252                                 if ( !scrollview.enableHandler() || clipLength > viewLength ) {
253                                         return;
254                                 }
255
256                                 if ( scrollview._handlerTimer ) {
257                                         clearTimeout( scrollview._handlerTimer );
258                                         scrollview._handlerTimer = 0;
259                                 }
260                                 scrollview._handlerTimer = setTimeout( function () {
261                                         if ( scrollview._timerID === 0 && $view.moveData === null ) {
262                                                 handlerThumb.removeClass( "ui-handler-visible" )
263                                                                         .stop( true, true )
264                                                                         .css( "opacity", 1.0 )
265                                                                         .fadeOut( 'fast' );
266                                                 scrollview._handlerTimer = 0;
267                                         }
268                                 }, 1000 );
269
270                                 event.preventDefault();
271                         }).bind( "mousewheel", function ( event ) {
272                                 handlerThumb.removeClass( "ui-handler-visible" ).hide();
273                                 setHanderPostion( scrollview.getScrollPosition() );
274                         });
275                 };
276
277         $.extend( $.tizen.scrollview.prototype, {
278                 enableHandler: function ( enabled ) {
279                         if ( typeof enabled === 'undefined' ) {
280                                 return this.options.handler;
281                         }
282
283                         this.options.handler = !!enabled;
284
285                         var view = this.element;
286                         if ( this.options.handler ) {
287                                 if ( view.find( ".ui-handler" ).length === 0 ) {
288                                         createHandler( view );
289                                 }
290
291                                 view.find( ".ui-scrollbar" ).hide();
292                                 view.find( ".ui-handler" ).show();
293                         } else {
294                                 view.find( ".ui-handler" ).hide();
295                                 view.find( ".ui-scrollbar" ).show();
296                         }
297                 },
298
299                 _setOption: function ( key, value ) {
300                         if ( key === "handler") {
301                                 this.enableHandler( value );
302                         } else {
303                                 originSetOption.call( this, key, value );
304                         }
305                 },
306
307                 _handlerTimer : 0
308         });
309
310         $( document ).delegate( ":jqmData(scroll)", "scrollviewcreate", function () {
311                 var widget = $( this );
312                 if ( widget.attr( "data-" + $.mobile.ns + "scroll" ) === "none"
313                                 || widget.jqmData( "handler" ) !== true ) {
314                         return;
315                 }
316                 widget.scrollview( "enableHandler", "true" );
317         });
318 } ( jQuery, document ) );