Export 0.1.63
[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-handlertheme : Set the widget theme ( optional )
38  *
39  * APIs:
40  *
41  *              enableHandler ( boolean )
42  *                      : Get or set the use of Handler.
43  *                      If the value is ‘true’, it will be run Handler.
44  *                      If the value is ‘false’, it will be not run Handler.
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="../../docs/lists/index.html">Adam Kinkaid</a></li>
55  *                              <li><a href="../../docs/lists/index.html">Alex Wickerham</a></li>
56  *                              <li><a href="../../docs/lists/index.html">Avery Johnson</a></li>
57  *                      </ul>
58  *              </div>
59  */
60
61 /**
62         @class handler
63         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:
64
65                 <div data-role="content" data-scroll="y" data-handler="true">
66                         <ul data-role="listview">
67                                 <li data-role="list-divider">A</li>
68                                 <li><a href="#">Adam Kinkaid</a></li>
69                                         ...
70                         </ul>
71                 </div>
72         
73         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.
74
75                 $("#.selector").scrollview("enableHandler", [enable]);
76 */
77 /**
78         @property {Boolean} data-handler
79         Enables the handler widget. The value must be set to true.
80 */
81 /**
82         @property {String} data-handler-theme
83         Sets the handler widget theme.
84 */      
85 ( function ( $, document, undefined ) {
86         // The options of handler in scrollview
87         $.tizen.scrollview.prototype.options.handler = false;
88         $.tizen.scrollview.prototype.options.handlerTheme = "s";
89
90         $.extend( $.tizen.scrollview.prototype, {
91                 enableHandler : function ( enabled ) {
92                         if ( typeof enabled === 'undefined' ) {
93                                 return this.options.handler;
94                         }
95
96                         this.options.handler = !!enabled;
97
98                         var view = this.element;
99                         if ( this.options.handler ) {
100                                 view.find( ".ui-scrollbar" ).hide();
101                                 view.find( ".ui-handler" ).show();
102                         } else {
103                                 view.find( ".ui-handler" ).hide();
104                                 view.find( ".ui-scrollbar" ).show();
105                         }
106                 },
107                 _handlerTimer : 0
108         });
109
110         $( document ).delegate( ":jqmData(scroll)", "scrollviewcreate", function () {
111                 if ( $( this ).attr( "data-" + $.mobile.ns + "scroll" ) === "none" ) {
112                         return;
113                 }
114
115                 if ( $( this ).jqmData("handler") !== true ) {
116                         return;
117                 }
118
119                 var self = this,
120                         $this = $( this ),
121                         scrollview = $this.data( "scrollview" ),
122                         prefix = "<div class=\"ui-handler ui-handler-",
123                         suffix = "\"><div class=\"ui-handler-track\"><div class=\"ui-handler-thumb\"></div></div></div>",
124                         direction = scrollview.options.direction,
125                         isHorizontal = ( scrollview.options.direction === "x" ),
126                         _$view = scrollview._$view,
127                         _$clip = scrollview._$clip,
128                         handler = null,
129                         handlerThumb = null,
130                         viewLength = 0,
131                         clipLength = 0,
132                         handlerHeight = 0,
133                         handlerMargin = 0,
134                         trackLength = 0,
135                         isTouchable = $.support.touch,
136                         dragStartEvt = ( isTouchable ? "touchstart" : "mousedown" ) + ".handler",
137                         dragMoveEvtDefault = ( isTouchable ? "touchmove" : "mousemove" ),
138                         dragMoveEvt = dragMoveEvtDefault + ".handler",
139                         dragStopEvt = ( isTouchable ? "touchend" : "mouseup" ) + ".handler";
140
141                 if ( $this.find( ".ui-handler-thumb" ).length !== 0 || typeof direction !== "string" ) {
142                         return;
143                 }
144
145                 $this.append( prefix + direction + suffix );
146                 handler = $this.find( ".ui-handler" );
147                 handlerThumb = $this.find( ".ui-handler-thumb" ).hide();
148                 handlerHeight = ( isHorizontal ? handlerThumb.width() : handlerThumb.height() );
149                 handlerMargin = ( isHorizontal ? parseInt( handler.css( "right" ), 10 ) : parseInt( handler.css( "bottom" ), 10 ) );
150
151                 scrollview.enableHandler( scrollview.options.handler );
152
153                 $.extend( self, {
154                         moveData : null
155                 });
156
157                 // handler drag
158                 handlerThumb.bind( dragStartEvt, {
159                         e : handlerThumb
160                 }, function ( event ) {
161                         scrollview._stopMScroll();
162
163                         var target = event.data.e, t = ( isTouchable ? event.originalEvent.targetTouches[0] : event );
164
165                         self.moveData = {
166                                 target : target,
167                                 X : parseInt( target.css( 'left' ), 10 ) || 0,
168                                 Y : parseInt( target.css( 'top' ), 10 ) || 0,
169                                 pX : t.pageX,
170                                 pY : t.pageY
171                         };
172                         clipLength = ( isHorizontal ? _$clip.width() : _$clip.height() );
173                         viewLength = ( isHorizontal ? _$view.outerWidth( true ) : _$view.outerHeight( true ) ) - clipLength;
174                         trackLength = clipLength - handlerHeight - handlerMargin;
175
176                         _$view.trigger( "scrollstart" );
177                         event.preventDefault();
178                         event.stopPropagation();
179
180                         $( document ).bind( dragMoveEvt, function ( event ) {
181                                 var moveData = self.moveData,
182                                         handlePos = 0,
183                                         scrollPos = 0,
184                                         t = ( isTouchable ? event.originalEvent.targetTouches[0] : event );
185
186                                 handlePos = ( isHorizontal ? moveData.X + t.pageX - moveData.pX : moveData.Y + t.pageY - moveData.pY );
187
188                                 if ( handlePos < 0 ) {
189                                         handlePos = 0;
190                                 }
191
192                                 if ( handlePos > trackLength ) {
193                                         handlePos = trackLength;
194                                 }
195                                 scrollPos = - Math.round( handlePos / trackLength * viewLength );
196
197                                 $this.attr( "display", "none" );
198                                 if ( isHorizontal ) {
199                                         scrollview._setScrollPosition( scrollPos, 0 );
200                                         moveData.target.css( {
201                                                 left : handlePos
202                                         });
203                                 } else {
204                                         scrollview._setScrollPosition( 0, scrollPos );
205                                         moveData.target.css( {
206                                                 top : handlePos
207                                         });
208                                 }
209                                 $this.attr( "display", "inline" );
210
211                                 event.preventDefault();
212                                 event.stopPropagation();
213                         }).bind( dragStopEvt, function ( event ) {
214                                 $( document ).unbind( dragMoveEvt ).unbind( dragStopEvt );
215
216                                 self.moveData = null;
217                                 _$view.trigger( "scrollstop" );
218
219                                 event.preventDefault();
220                         });
221                 });
222
223                 $( document ).bind( dragMoveEvtDefault, function ( event ) {
224                         var isVisible = false,
225                                 vclass = "ui-scrollbar-visible";
226
227                         if ( scrollview._$vScrollBar ) {
228                                 isVisible = scrollview._$vScrollBar.hasClass( vclass );
229                         } else if ( scrollview._$hScrollBar ) {
230                                 isVisible = scrollview._$hScrollBar.hasClass( vclass );
231                         }
232
233                         if ( isVisible || self.moveData !== null ) {
234                                 if ( handlerThumb.hasClass( "ui-handler-visible" ) ) {
235                                         _$view.trigger( "scrollupdate" );
236                                 } else {
237                                         _$view.trigger( "scrollstart" );
238                                 }
239                         }
240                 });
241
242                 $this.bind( "scrollstart", function ( event ) {
243                         if ( !scrollview.enableHandler() ) {
244                                 return;
245                         }
246                         clipLength = ( isHorizontal ? _$clip.width() : _$clip.height() );
247                         viewLength = ( isHorizontal ? _$view.outerWidth( true ) : _$view.outerHeight( true ) ) - clipLength;
248                         trackLength = clipLength - handlerHeight - handlerMargin;
249
250                         if ( clipLength > viewLength || trackLength < ( handlerHeight * 4 / 3 ) ) {
251                                 return;
252                         }
253
254                         handlerThumb.addClass( "ui-handler-visible" );
255                         handlerThumb.stop().fadeIn( 'fast' );
256
257                         event.preventDefault();
258                         event.stopPropagation();
259                 }).bind( "scrollupdate", function ( event, data ) {
260                         if ( !scrollview.enableHandler() || clipLength > viewLength || trackLength < ( handlerHeight * 4 / 3 ) ) {
261                                 return;
262                         }
263
264                         var scrollPos = scrollview.getScrollPosition(), handlerPos = 0;
265
266                         handlerThumb.stop( true, true ).hide().css( "opacity", 1.0 );
267
268                         if ( isHorizontal ) {
269                                 handlerPos = Math.round( scrollPos.x / viewLength * trackLength );
270                                 handlerThumb.css( "left", handlerPos );
271                         } else {
272                                 handlerPos = Math.round( scrollPos.y / viewLength * trackLength );
273                                 handlerThumb.css( "top", handlerPos );
274                         }
275
276                         handlerThumb.show();
277
278                         event.preventDefault();
279                         event.stopPropagation();
280                 }).bind( "scrollstop", function ( event ) {
281                         if ( !scrollview.enableHandler() || clipLength > viewLength ) {
282                                 return;
283                         }
284
285                         scrollview._handlerTimer = setTimeout( function () {
286                                 if ( scrollview._timerID === 0 && self.moveData === null ) {
287                                         handlerThumb.removeClass( "ui-handler-visible" );
288                                         handlerThumb.stop( true, true ).fadeOut( 'fast' );
289                                         clearTimeout( scrollview._handlerTimer );
290                                         scrollview._handlerTimer = 0;
291                                 }
292                         }, 1000 );
293
294                         event.preventDefault();
295                 });
296         });
297 } ( jQuery, document ) );