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