2 /* ***************************************************************************
3 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 * ***************************************************************************
24 * Authors: Wonseop Kim ( wonseop.kim@samsung.com )
28 * "Handler" is a widget helping a user to scroll a window or panel.
29 * It is different from the scrollview feature in that the handler has a fixed size
30 * and disappears when a scroll size is smaller than a parent window's size.
31 * If the handler widget is activated, a scroll bar on the screen will be deactivated.
32 * The handler widget supports scrolling up and down and indicates the position of the scrolled window.
36 * data-handler : This attribute is indicating that whether enable.
37 * If you want to use, you will set 'true'.
38 * data-handler-theme : Set the widget theme ( optional )
42 * enableHandler ( boolean )
43 * : Get or set the use of handler widget.
44 * If the value is "true", it will be run handler widget.
45 * If the value is "false", it will be not run handler widget.
46 * If no value is specified, will act as a getter.
52 * <div data-role="content" data-scroll="y" data-handler="true">
53 * <ul data-role="listview">
54 * <li data-role="list-divider">A</li>
55 * <li><a href="#">Adam Kinkaid</a></li>
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:
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>
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.
75 $("#.selector").scrollview("enableHandler", [enable]);
78 @property {Boolean} data-handler
79 Enables the handler widget. The value must be set to true.
82 @property {String} data-handler-theme
83 Sets the handler widget theme.
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";
90 var originSetOption = $.tizen.scrollview.prototype._setOption,
91 createHandler = function ( target ) {
93 prefix = "<div class=\"ui-handler ui-handler-direction-",
94 suffix = "\"><div class=\"ui-handler-track\"><div class=\"ui-handler-handle\"><div class=\"ui-handler-thumb\"></div></div></div></div>",
95 scrollview = $view.data( "scrollview" ),
96 options = scrollview.options,
97 direction = options.direction,
98 parentTheme = $.mobile.getInheritedTheme( scrollview, "s" ),
99 theme = options.theme || parentTheme,
100 isHorizontal = ( scrollview.options.direction === "x" ),
101 _$view = scrollview._$view,
102 _$clip = scrollview._$clip,
103 scrollbar = $view.find( ".ui-scrollbar" ),
105 handlerHandle = null,
112 isTouchable = $.support.touch,
113 dragStartEvt = ( isTouchable ? "touchstart" : "mousedown" ) + ".handler",
114 dragMoveEvt = ( isTouchable ? "touchmove" : "mousemove" ) + ".handler",
115 dragStopEvt = ( isTouchable ? "touchend" : "mouseup" ) + ".handler",
116 dragLeaveEvt = ( isTouchable ? " touchleave" : " mouseleave" ) + ".handler",
117 calculateLength = function () {
118 clipLength = ( isHorizontal ? _$clip.width() : _$clip.height() );
119 viewLength = ( isHorizontal ? _$view.width() : _$view.height() ) - clipLength;
120 trackLength = clipLength - handlerHeight - handlerMargin * 2;
122 setHanderPostion = function ( scrollPos ) {
123 var handlerPos = Math.round( ( isHorizontal ? scrollPos.x : scrollPos.y ) / viewLength * trackLength );
124 handlerHandle[0].style[ ( isHorizontal ? "left" : "top" ) ] = handlerPos + "px";
126 stopHandlerScroll = function () {
127 $( document ).unbind( ".handler" );
128 $view.moveData = null;
129 _$view.trigger( "scrollstop" );
132 if ( $view.find( ".ui-handler-handle" ).length !== 0 || typeof direction !== "string" ) {
136 handler = $( [ prefix, direction, suffix ].join( "" ) ).appendTo( $view.addClass( " ui-handler-" + theme ) );
137 handlerHandle = $view.find( ".ui-handler-handle" ).attr( {
139 "aria-label" : ( isHorizontal ? "Horizontal handler, double tap and move to scroll" : "Verticalhandler, double tap and move to scroll" )
141 handlerHeight = ( isHorizontal ? handlerHandle.width() : handlerHandle.height() );
142 handlerMargin = ( isHorizontal ? parseInt( handler.css( "right" ), 10 ) : parseInt( handler.css( "bottom" ), 10 ) );
149 handlerHandle.bind( dragStartEvt, {
151 }, function ( event ) {
152 scrollview._stopMScroll();
154 var target = event.data.e,
155 t = ( isTouchable ? event.originalEvent.targetTouches[0] : event );
157 target.style.opacity = 1.0;
161 X : parseInt( target.style.left, 10 ) || 0,
162 Y : parseInt( target.style.top, 10 ) || 0,
168 _$view.trigger( "scrollstart" );
170 if ( !isTouchable ) {
171 event.preventDefault();
174 $( document ).bind( dragMoveEvt, function ( event ) {
175 var moveData = $view.moveData,
176 target = moveData.target,
179 t = ( isTouchable ? event.originalEvent.targetTouches[0] : event );
181 handlePos = ( isHorizontal ? moveData.X + t.pageX - moveData.pX : moveData.Y + t.pageY - moveData.pY );
183 if ( handlePos < 0 ) {
187 if ( handlePos > trackLength ) {
188 handlePos = trackLength;
190 scrollPos = - Math.round( handlePos / trackLength * viewLength );
192 if ( isHorizontal ) {
193 scrollview._setScrollPosition( scrollPos, 0 );
194 target.style.left = handlePos + "px";
196 scrollview._setScrollPosition( 0, scrollPos );
197 target.style.top = handlePos + "px";
200 event.preventDefault();
201 }).bind( dragStopEvt + dragLeaveEvt, function ( event ) {
206 _$view.bind( dragStopEvt, function ( event ) {
210 $view.bind( "scrollstart", function ( event ) {
211 if ( !scrollview.enableHandler() ) {
217 if ( viewLength < 0 || clipLength < handlerHeight ) {
218 if ( scrollbar.is( ":hidden" ) ) {
224 if ( scrollbar.is( ":visible" ) ) {
229 clearInterval( moveTimer );
230 moveTimer = undefined;
233 handler.addClass( "ui-handler-visible" );
234 handlerHandle.stop( true, true )
236 }).bind( "scrollupdate", function ( event, data ) {
237 if ( !scrollview.enableHandler() || viewLength < 0 || clipLength < handlerHeight ) {
241 setHanderPostion( scrollview.getScrollPosition() );
242 }).bind( "scrollstop", function ( event ) {
243 if ( !scrollview.enableHandler() || viewLength < 0 || clipLength < handlerHeight ) {
247 moveTimer = setInterval( function () {
248 setHanderPostion( scrollview.getScrollPosition() );
249 if ( !scrollview._gesture_timer ) {
250 clearInterval( moveTimer );
251 moveTimer = undefined;
255 if ( scrollview._handlerTimer ) {
256 clearTimeout( scrollview._handlerTimer );
257 scrollview._handlerTimer = 0;
259 scrollview._handlerTimer = setTimeout( function () {
260 if ( scrollview._timerID === 0 && $view.moveData === null ) {
261 handlerHandle.stop( true, true )
262 .css( "opacity", 1.0 )
263 .fadeOut( function () {
264 handler.removeClass( "ui-handler-visible" );
266 scrollview._handlerTimer = 0;
269 }).bind( "mousewheel", function ( event ) {
270 handler.removeClass( "ui-handler-visible" );
271 setHanderPostion( scrollview.getScrollPosition() );
275 $.extend( $.tizen.scrollview.prototype, {
276 enableHandler: function ( enabled ) {
277 if ( typeof enabled === 'undefined' ) {
278 return this.options.handler;
281 this.options.handler = !!enabled;
283 var $view = this.element;
284 if ( this.options.handler ) {
285 if ( $view.find( ".ui-handler" ).length === 0 ) {
286 createHandler( $view );
289 $view.find( ".ui-scrollbar" ).hide();
290 $view.find( ".ui-handler" ).show();
292 $view.find( ".ui-handler" ).removeClass( "ui-handler-visible" ).hide();
293 $view.find( ".ui-scrollbar" ).show();
297 _setHandlerTheme: function ( handlerTheme ) {
298 if ( !handlerTheme ) {
302 var oldClass = "ui-handler-" + this.options.handlerTheme,
303 newClass = "ui-handler-" + handlerTheme;
305 this.element.removeClass( oldClass ).addClass( newClass );
306 this.options.handlerTheme = handlerTheme;
309 _setOption: function ( key, value ) {
312 this.enableHandler( value );
315 this._setHandlerTheme( value );
318 originSetOption.call( this, key, value );
325 $( document ).delegate( ":jqmData(scroll)", "scrollviewcreate", function () {
326 var widget = $( this );
327 if ( widget.attr( "data-" + $.mobile.ns + "scroll" ) === "none"
328 || widget.attr( "data-" + $.mobile.ns + "handler" ) !== "true" ) {
331 widget.scrollview( "enableHandler", "true" );
333 } ( jQuery, document ) );