You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pp...@apache.org on 2013/09/10 20:04:21 UTC
[16/51] [partial] [cordova-tizen] Tizen SDK 2.2 support mores samples
http://git-wip-us.apache.org/repos/asf/cordova-tizen/blob/4ebce38e/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/jquery.mobile.tizen.pinch.js
----------------------------------------------------------------------
diff --git a/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/jquery.mobile.tizen.pinch.js b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/jquery.mobile.tizen.pinch.js
new file mode 100644
index 0000000..cece62a
--- /dev/null
+++ b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/jquery.mobile.tizen.pinch.js
@@ -0,0 +1,373 @@
+/* ***************************************************************************
+ Flora License
+
+ Version 1.1, April, 2013
+
+ http://floralicense.org/license/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and
+ all other entities that control, are controlled by, or are
+ under common control with that entity. For the purposes of
+ this definition, "control" means (i) the power, direct or indirect,
+ to cause the direction or management of such entity,
+ whether by contract or otherwise, or (ii) ownership of fifty percent (50%)
+ or more of the outstanding shares, or (iii) beneficial ownership of
+ such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation source,
+ and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or Object form,
+ made available under the License, as indicated by a copyright notice
+ that is included in or attached to the work (an example is provided
+ in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object form,
+ that is based on (or derived from) the Work and for which the editorial
+ revisions, annotations, elaborations, or other modifications represent,
+ as a whole, an original work of authorship. For the purposes of this License,
+ Derivative Works shall not include works that remain separable from,
+ or merely link (or bind by name) to the interfaces of, the Work and
+ Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including the original
+ version of the Work and any modifications or additions to that Work or
+ Derivative Works thereof, that is intentionally submitted to Licensor
+ for inclusion in the Work by the copyright owner or by an individual or
+ Legal Entity authorized to submit on behalf of the copyright owner.
+ For the purposes of this definition, "submitted" means any form of
+ electronic, verbal, or written communication sent to the Licensor or
+ its representatives, including but not limited to communication on
+ electronic mailing lists, source code control systems, and issue
+ tracking systems that are managed by, or on behalf of, the Licensor
+ for the purpose of discussing and improving the Work, but excluding
+ communication that is conspicuously marked or otherwise designated
+ in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ "Tizen Certified Platform" shall mean a software platform that complies
+ with the standards set forth in the Tizen Compliance Specification
+ and passes the Tizen Compliance Tests as defined from time to time
+ by the Tizen Technical Steering Group and certified by the Tizen
+ Association or its designated agent.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work
+ solely as incorporated into a Tizen Certified Platform, where such
+ license applies only to those patent claims licensable by such
+ Contributor that are necessarily infringed by their Contribution(s)
+ alone or by combination of their Contribution(s) with the Work solely
+ as incorporated into a Tizen Certified Platform to which such
+ Contribution(s) was submitted. If You institute patent litigation
+ against any entity (including a cross-claim or counterclaim
+ in a lawsuit) alleging that the Work or a Contribution incorporated
+ within the Work constitutes direct or contributory patent infringement,
+ then any patent licenses granted to You under this License for that
+ Work shall terminate as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof pursuant to the copyright license
+ above, in any medium, with or without modifications, and in Source or
+ Object form, provided that You meet the following conditions:
+
+ 1. You must give any other recipients of the Work or Derivative Works
+ a copy of this License; and
+ 2. You must cause any modified files to carry prominent notices stating
+ that You changed the files; and
+ 3. You must retain, in the Source form of any Derivative Works that
+ You distribute, all copyright, patent, trademark, and attribution
+ notices from the Source form of the Work, excluding those notices
+ that do not pertain to any part of the Derivative Works; and
+ 4. If the Work includes a "NOTICE" text file as part of its distribution,
+ then any Derivative Works that You distribute must include a readable
+ copy of the attribution notices contained within such NOTICE file,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works, in at least one of the following places:
+ within a NOTICE text file distributed as part of the Derivative Works;
+ within the Source form or documentation, if provided along with the
+ Derivative Works; or, within a display generated by the Derivative Works,
+ if and wherever such third-party notices normally appear.
+ The contents of the NOTICE file are for informational purposes only
+ and do not modify the License.
+
+ You may add Your own attribution notices within Derivative Works
+ that You distribute, alongside or as an addendum to the NOTICE text
+ from the Work, provided that such additional attribution notices
+ cannot be construed as modifying the License. You may add Your own
+ copyright statement to Your modifications and may provide additional or
+ different license terms and conditions for use, reproduction, or
+ distribution of Your modifications, or for any such Derivative Works
+ as a whole, provided Your use, reproduction, and distribution of
+ the Work otherwise complies with the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Flora License to your work
+
+ To apply the Flora License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Flora License, Version 1.1 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://floralicense.org/license/
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ * Author: Minkyu Kang <mk...@samsung.com>
+ */
+
+/*
+ * Pinch Event
+ *
+ * Events
+ * pinchstart: triggered when start the touched two points
+ * pinch: triggered when move the touch point after pinchstart event occured
+ * pinchend: triggered when touchend event after pinchstart event occured
+ *
+ * Parameters
+ * point: touched points
+ * ratio: origin point-to-current point ratio for moving distance
+ *
+ * $("#pinch").bind("pinch", function (e, p) {
+ * console.log("point[0].x: " + p.point[0].x);
+ * console.log("point[0].y: " + p.point[0].y);
+ * console.log("point[1].x: " + p.point[1].x);
+ * console.log("point[1].y: " + p.point[1].y);
+ * console.log("ratio: " + p.ratio);
+ * });
+ *
+ * Options
+ * $.mobile.pinch.enabled: true or false
+ * $.mobile.pinch.min: minimum value of ratio
+ * $.mobile.pinch.max: maximum value of ratio
+ * $.mobile.pinch.factor: scale factor of ratio
+ * $.mobile.pinch.threshold: move threshold of ratio
+ * $.mobile.pinch.interval: interval for pinch event
+ */
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+//>>description: Pinch Event
+//>>label: Pinch Event
+//>>group: Tizen:Core
+
+define( [
+ 'jquery',
+ 'jqm/jquery.mobile.core'
+ ], function ( jQuery ) {
+
+//>>excludeEnd("jqmBuildExclude");
+
+( function( $, window, undefined ) {
+
+pinch_event = {
+ setup: function () {
+ var thisObject = this,
+ $this = $( thisObject );
+
+ if ( !$.mobile.support.touch ) {
+ return;
+ }
+
+ function getSize( point ) {
+ var x = point[0].x - point[1].x,
+ y = point[0].y - point[1].y;
+
+ return Math.abs( x * y );
+ }
+
+ function getParameter( point, ratio ) {
+ return { point: point, ratio: ratio };
+ }
+
+ $this.bind( "touchstart", function ( event ) {
+ var data = event.originalEvent.touches,
+ origin,
+ last_ratio = 1,
+ processing = false;
+
+ if ( !$.mobile.pinch.enabled ) {
+ return;
+ }
+
+ if ( data.length != 2 ) {
+ return;
+ }
+
+ origin = [
+ { x: data[0].pageX, y: data[0].pageY },
+ { x: data[1].pageX, y: data[1].pageY }
+ ];
+
+ $( event.target ).trigger( "pinchstart", getParameter( origin, undefined ) );
+
+ function pinchHandler( event ) {
+ var data = event.originalEvent.touches,
+ current,
+ ratio,
+ delta,
+ factor = $( window ).width() / $.mobile.pinch.factor;
+
+ if ( processing ) {
+ return;
+ }
+
+ if ( !origin ) {
+ return;
+ }
+
+ current = [
+ { x: data[0].pageX, y: data[0].pageY },
+ { x: data[1].pageX, y: data[1].pageY }
+ ];
+
+ delta = Math.sqrt( getSize( current ) / getSize( origin ) ) ;
+ if( delta ) {
+ ratio = delta;
+ }
+
+ if ( ratio < $.mobile.pinch.min ) {
+ ratio = $.mobile.pinch.min;
+ } else if ( ratio > $.mobile.pinch.max ) {
+ ratio = $.mobile.pinch.max;
+ }
+
+ if ( Math.abs( ratio - last_ratio ) < $.mobile.pinch.threshold ) {
+ return;
+ }
+
+ $( event.target ).trigger( "pinch", getParameter( current, ratio ) );
+
+ last_ratio = ratio;
+
+ if ( $.mobile.pinch.interval ) {
+ processing = true;
+
+ setTimeout( function () {
+ processing = false;
+ }, $.mobile.pinch.interval );
+ }
+ }
+
+ $this.bind( "touchmove", pinchHandler )
+ .one( "touchend", function ( event ) {
+ $this.unbind( "touchmove", pinchHandler );
+ $( event.target ).trigger( "pinchend",
+ getParameter( undefined, last_ratio ) );
+
+ origin = undefined;
+ current = undefined;
+ last_ratio = 1;
+ processing = false;
+ });
+ });
+ }
+};
+
+$.event.special["pinch"] = pinch_event;
+
+$.mobile.pinch = {
+ enabled: true,
+ min: 0.1,
+ max: 3,
+ factor: 4,
+ threshold: 0.01,
+ interval: 50
+};
+
+})( jQuery, this );
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+} );
+//>>excludeEnd("jqmBuildExclude");
http://git-wip-us.apache.org/repos/asf/cordova-tizen/blob/4ebce38e/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/jquery.mobile.tizen.scrollview.js
----------------------------------------------------------------------
diff --git a/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/jquery.mobile.tizen.scrollview.js b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/jquery.mobile.tizen.scrollview.js
new file mode 100644
index 0000000..baeb51b
--- /dev/null
+++ b/samples/TizenWebUI-sample-v1/tizen-web-ui-fw/latest/js/modules/jquery.mobile.tizen.scrollview.js
@@ -0,0 +1,1942 @@
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+//>>description: Implements scroll by javascript
+//>>label: Scrollview
+//>>group: Tizen:Core
+
+define( [
+ "jquery",
+ "jqm/jquery.mobile.widget",
+ 'libs/jquery.easing.1.3'
+ ], function ( jQuery ) {
+
+//>>excludeEnd("jqmBuildExclude");
+
+/*
+* jQuery Mobile Framework : scrollview plugin
+* Copyright (c) 2010 Adobe Systems Incorporated - Kin Blas (jblas@adobe.com)
+* Licensed under the MIT (MIT-LICENSE.txt) license.
+* Note: Code is in draft form and is subject to change
+* Modified by Koeun Choi <ko...@samsung.com>
+* Modified by Minkyu Kang <mk...@samsung.com>
+*/
+
+(function ( $, window, document, undefined ) {
+
+ /**
+ * Resizes page content height according to footer
+ * header elements, and page padding
+ * @param {HTMLElement|jQuery} page
+ */
+ function resizePageContentHeight( page ) {
+ var $page = $( page ),
+ $content = $page.children(".ui-content"),
+ hh = $page.children(".ui-header").outerHeight() || 0,
+ fh = $page.children(".ui-footer").outerHeight() || 0,
+ pt = parseFloat( $content.css("padding-top") ),
+ pb = parseFloat( $content.css("padding-bottom") ),
+ wh = $( window ).height();
+
+ $content.height( wh - (hh + fh) - (pt + pb) );
+ }
+
+ /**
+ * MomentumTracker - helper class to ease momentum
+ * movement calculations
+ * @class
+ * @param {Object} options
+ */
+ function MomentumTracker( options ) {
+ this.options = $.extend( {}, options );
+ this.easing = "easeOutQuad";
+ this.reset();
+ }
+
+ /**
+ * Scroll states dictionary
+ * @type {Object}
+ */
+ var tstates = {
+ scrolling: 0,
+ overshot: 1,
+ snapback: 2,
+ done: 3
+ };
+
+ /**
+ * Returns current time in miliseconds
+ * @return {number}
+ */
+ function getCurrentTime() {
+ return Date.now();
+ };
+
+ function bitwiseAbs( e ) {
+ return ( e ^ (e>>31)) - (e>>31);
+ }
+
+ jQuery.widget( "tizen.scrollview", jQuery.mobile.widget, {
+ /**
+ * Default options
+ * @type {Object}
+ */
+ options: {
+ /**
+ * Direction of scroll, can be:
+ * "x" for horizontal scroll
+ * "y" for vertical scroll
+ * null for horizontal and vertical scroll
+ * @type {string|null}
+ */
+ direction: null, // "x", "y", or null for both.
+
+ /**
+ * Internal timer inteval
+ * @type {number}
+ */
+ timerInterval: 10,
+
+ /**
+ * Duration of the scrolling animation in miliseconds
+ * @type {number}
+ */
+ scrollDuration: 1000,
+
+ /**
+ * Duration of the overshoot animation in miliseconds
+ * @type {number}
+ */
+ overshootDuration: 250,
+
+ /**
+ * Duration of snapback animation in miliseconds
+ * @type {number}
+ */
+ snapbackDuration: 500,
+
+ /**
+ * Scroll detection threshold
+ * @type {number}
+ */
+ moveThreshold: 10,
+
+ /**
+ * Maximal time between mouse movements while scrolling
+ * @type {number}
+ */
+ moveIntervalThreshold: 150,
+
+ /**
+ * Scroll method type, can be "translate" or "position"
+ * @type {string}
+ */
+ scrollMethod: "translate",
+
+ /**
+ * The event fired when started scrolling
+ * @type {string}
+ */
+ startEventName: "scrollstart",
+
+ /**
+ * The event fired on each scroll update (movement)
+ * @type {string}
+ */
+ updateEventName: "scrollupdate",
+
+ /**
+ * The event fired after scroll stopped
+ * @type {string}
+ */
+ stopEventName: "scrollstop",
+
+ /**
+ * Determines the event group for detecting scroll
+ * if $.support.touch has truthy value the group
+ * that starts scroll will be touch events, otherwise
+ * mouse events will be used
+ * @type {string}
+ */
+ eventType: $.support.touch ? "touch" : "mouse",
+
+ /**
+ * Determines if we should show the scrollbars
+ * @type {boolean}
+ */
+ showScrollBars: true,
+
+ /**
+ * Determines if overshoot animation is enabled
+ * @type {boolean}
+ */
+ overshootEnable: false,
+
+ /**
+ * Determines if we enable the window scroll
+ * @type {boolean}
+ */
+ outerScrollEnable: false,
+
+ /**
+ * Determines if the overflow animation is enabled
+ * @type {boolean}
+ */
+ overflowEnable: true,
+
+ /**
+ * Determines if we allow scroll jumps
+ * @type {boolean}
+ */
+ scrollJump: false
+ },
+
+ /**
+ * Returns view height
+ * @private
+ * @return {number}
+ */
+ _getViewHeight: function () {
+ return this._$view.height();
+ },
+
+ /**
+ * Returns view width
+ * @private
+ * @return {number}
+ */
+ _getViewWidth: function () {
+ return this._$view.width();
+ },
+
+ /**
+ * Changes specified elements position to relative if
+ * previous position state was static
+ * @private
+ * @param {jQuery} $ele
+ */
+ _makePositioned: function ( $ele ) {
+ if ( $ele.css("position") === "static" ) {
+ $ele.css( "position", "relative" );
+ }
+ },
+
+ /**
+ * Creates scrollview widget,
+ * binds events and initiaties timers
+ * @private
+ */
+ _create: function () {
+ var direction,
+ self = this;
+
+ this._$clip = $( this.element ).addClass("ui-scrollview-clip");
+
+ if ( this._$clip.children(".ui-scrollview-view").length ) {
+ this._$view = this._$clip.children(".ui-scrollview-view");
+ } else {
+ this._$view = this._$clip.wrapInner("<div></div>").children()
+ .addClass("ui-scrollview-view");
+ }
+
+ if ( this.options.scrollMethod === "translate" ) {
+ if ( this._$view.css("transform") === undefined ) {
+ this.options.scrollMethod = "position";
+ }
+ }
+
+ this._$clip.css( "overflow", "hidden" );
+ this._makePositioned( this._$clip );
+
+ this._makePositioned( this._$view );
+ this._$view.css( { left: 0, top: 0 } );
+
+ this._view_height = this._getViewHeight();
+
+ this._sx = 0;
+ this._sy = 0;
+
+ direction = this.options.direction;
+
+ this._hTracker = ( direction !== "y" ) ?
+ new MomentumTracker( this.options ) : null;
+ this._vTracker = ( direction !== "x" ) ?
+ new MomentumTracker( this.options ) : null;
+
+ this._timerInterval = this.options.timerInterval;
+ this._timerID = 0;
+
+ this._timerCB = function () {
+ self._handleMomentumScroll();
+ };
+
+ this._add_event();
+ this._add_scrollbar();
+ this._add_scroll_jump();
+ this._add_overflow_indicator();
+ this._moveInterval = 10; /* Add Interval */
+ this._clipHeight = 0;
+ },
+
+ /**
+ * Starts momentum scroll after user stopped
+ * scrolling
+ * @private
+ * @param {number} speedX Horizontal speed
+ * @param {number} speedY Vertical speed
+ */
+ _startMScroll: function ( speedX, speedY ) {
+ var keepGoing = false,
+ duration = this.options.scrollDuration,
+ ht = this._hTracker,
+ vt = this._vTracker,
+ c,
+ v;
+
+ this._$clip.trigger( this.options.startEventName );
+
+ if ( ht ) {
+ c = this._$clip.width();
+ v = this._getViewWidth();
+
+ if ( (( this._sx === 0 && speedX > 0 ) ||
+ ( this._sx === -(v - c) && speedX < 0 )) &&
+ v > c ) {
+ return;
+ }
+
+ ht.start( this._sx, speedX,
+ duration, (v > c) ? -(v - c) : 0, 0 );
+ keepGoing = !ht.done();
+ }
+
+ if ( vt ) {
+ c = this._$clip.height();
+ v = this._getViewHeight();
+
+ if ( (( this._sy === 0 && speedY > 0 ) ||
+ ( this._sy === -(v - c) && speedY < 0 )) &&
+ v > c ) {
+ return;
+ }
+
+ vt.start( this._sy, speedY,
+ duration, (v > c) ? -(v - c) : 0, 0 );
+ keepGoing = keepGoing || !vt.done();
+ }
+
+ if ( keepGoing ) {
+ this._timerID = setTimeout( this._timerCB, this._timerInterval );
+ } else {
+ this._stopMScroll();
+ }
+ },
+
+ /**
+ * Ends momentum scroll
+ * @private
+ */
+ _stopMScroll: function () {
+ if ( this._timerID ) {
+ this._$clip.trigger( this.options.stopEventName );
+ clearTimeout( this._timerID );
+ }
+ this._timerID = 0;
+
+ if ( this._vTracker ) {
+ this._vTracker.reset();
+ }
+
+ if ( this._hTracker ) {
+ this._hTracker.reset();
+ }
+
+ this._hideScrollBars();
+ this._hideOverflowIndicator();
+ },
+
+ /**
+ * Updates scroll while in momentum scroll mode
+ * @private
+ */
+ _handleMomentumScroll: function () {
+ var keepGoing = false,
+ x = 0,
+ y = 0,
+ scroll_height = 0,
+ self = this,
+ vt = this._vTracker,
+ ht = this._hTracker;
+
+ if ( this._outerScrolling ) {
+ return;
+ }
+
+ if ( vt ) {
+ vt.update( this.options.overshootEnable );
+ y = vt.getPosition();
+ keepGoing = !vt.done();
+
+ if ( vt.getRemained() > this.options.overshootDuration ) {
+ scroll_height = this._getViewHeight() - this._$clip.height();
+
+ if ( !vt.isAvail() ) {
+ if ( this._speedY > 0 ) {
+ this._outerScroll( vt.getRemained() / 3, scroll_height );
+ } else {
+ this._outerScroll( y - vt.getRemained() / 3, scroll_height );
+ }
+ } else if ( vt.isMin() ) {
+ this._outerScroll( y - vt.getRemained() / 3, scroll_height );
+
+ } else if ( vt.isMax() ) {
+ this._outerScroll( vt.getRemained() / 3, scroll_height );
+ }
+ }
+ }
+
+ if ( ht ) {
+ ht.update( this.options.overshootEnable );
+ x = ht.getPosition();
+ keepGoing = keepGoing || !ht.done();
+ }
+
+ this._setScrollPosition( x, y );
+ this._$clip.trigger( this.options.updateEventName,
+ [ { x: x, y: y } ] );
+
+ if ( keepGoing ) {
+ this._timerID = setTimeout( this._timerCB, this._timerInterval );
+ } else {
+ this._stopMScroll();
+ }
+ },
+
+ /**
+ * Sets css translate transformation for element
+ * @param {jQuery} $ele
+ * @param {number} x
+ * @param {number} y
+ * @param {number} duration
+ */
+ _setElementTransform: function ( $ele, x, y, duration ) {
+ var translate,
+ transition;
+
+ if ( !duration || duration === undefined ) {
+ transition = "none";
+ } else {
+ transition = "-webkit-transform " + duration / 1000 + "s ease-out";
+ }
+
+ if ( $.support.cssTransform3d ) {
+ translate = "translate3d(" + x + "," + y + ", 0px)";
+ } else {
+ translate = "translate(" + x + "," + y + ")";
+ }
+
+ $ele.css({
+ "-moz-transform": translate,
+ "-webkit-transform": translate,
+ "-ms-transform": translate,
+ "-o-transform": translate,
+ "transform": translate,
+ "-webkit-transition": transition
+ });
+ },
+
+ /**
+ * Applies scroll end effect according to direction
+ * @param {string} dir Direction, can be "in" or "out"
+ */
+ _setEndEffect: function ( dir ) {
+ var scroll_height = this._getViewHeight() - this._$clip.height();
+
+ if ( this._softkeyboard ) {
+ if ( this._effect_dir ) {
+ this._outerScroll( -scroll_height - this._softkeyboardHeight,
+ scroll_height );
+ } else {
+ this._outerScroll( this._softkeyboardHeight, scroll_height );
+ }
+ return;
+ }
+
+ if ( dir === "in" ) {
+ if ( this._endEffect ) {
+ return;
+ }
+
+ this._endEffect = true;
+ this._setOverflowIndicator( this._effect_dir );
+ this._showOverflowIndicator();
+ } else if ( dir === "out" ) {
+ if ( !this._endEffect ) {
+ return;
+ }
+
+ this._endEffect = false;
+ } else {
+ this._endEffect = false;
+ this._setOverflowIndicator();
+ this._showOverflowIndicator();
+ }
+ },
+
+ /**
+ * Calibrates scroll position and scroll end effect
+ * @private
+ * @param {number} x
+ * @param {number} y
+ */
+ _setCalibration: function ( x, y ) {
+ if ( this.options.overshootEnable ) {
+ this._sx = x;
+ this._sy = y;
+ return;
+ }
+
+ var $v = this._$view,
+ $c = this._$clip,
+ dirLock = this._directionLock,
+ scroll_height = 0,
+ scroll_width = 0,
+ vh,
+ ch;
+
+ if ( dirLock !== "y" && this._hTracker ) {
+ scroll_width = $v.width() - $c.width();
+
+ if ( x >= 0 ) {
+ this._sx = 0;
+ } else if ( x < -scroll_width ) {
+ this._sx = -scroll_width;
+ } else {
+ this._sx = x;
+ }
+
+ if ( scroll_width < 0 ) {
+ this._sx = 0;
+ }
+ }
+
+ if ( dirLock !== "x" && this._vTracker ) {
+ vh = this._getViewHeight();
+ ch = $c.height();
+ /*
+ When used changePage() function, this._getViewHeight() value set 0.
+ So scroll_height has incorrect value and showed indicator incorrectly.
+ Below condition is exception handling that avoid this situation.
+ */
+ if ( vh != 0 && ch > 0 ) {
+ scroll_height = vh - ch;
+ }
+
+ if ( y > 0 ) {
+ this._sy = 0;
+
+ this._effect_dir = 0;
+ this._setEndEffect( "in" );
+ } else if ( y < -scroll_height ) {
+ this._sy = -scroll_height;
+
+ this._effect_dir = 1;
+ this._setEndEffect( "in" );
+ } else {
+ if ( this._endEffect && this._sy !== y ) {
+ this._setEndEffect();
+ }
+
+ this._sy = y;
+ }
+
+ if ( scroll_height < 0 ) {
+ this._sy = 0;
+ }
+ }
+ },
+
+ /**
+ * Moves scroll to specified position
+ * @private
+ * @param {number} x
+ * @param {number} y
+ * @param {number} duration
+ */
+ _setScrollPosition: function ( x, y, duration ) {
+ var $v = this._$view,
+ sm = this.options.scrollMethod,
+ $vsb = this._$vScrollBar,
+ $hsb = this._$hScrollBar,
+ $sbt;
+
+ this._setCalibration( x, y );
+
+ x = this._sx;
+ y = this._sy;
+
+ if ( sm === "translate" ) {
+ this._setElementTransform( $v, x + "px", y + "px", duration );
+ } else {
+ $v.css( {left: x + "px", top: y + "px"} );
+ }
+
+ if ( $vsb ) {
+ $sbt = $vsb.find(".ui-scrollbar-thumb");
+
+ if ( sm === "translate" ) {
+ if ( bitwiseAbs( this._moveInterval - bitwiseAbs(y)) > 20 ) {
+ /* update scrollbar every 20(clientY) move*/
+ /* Add Interval */
+ this._setElementTransform( $sbt, "0px",
+ -y / this._getViewHeight() * this._clipHeight + "px",
+ duration );
+ }
+ } else {
+ $sbt.css( "top", -y / this._getViewHeight() * 100 + "%" );
+ }
+ }
+
+ if ( $hsb ) {
+ $sbt = $hsb.find(".ui-scrollbar-thumb");
+
+ if ( sm === "translate" ) {
+ this._setElementTransform( $sbt,
+ -x / $v.outerWidth() * $sbt.parent().width() + "px", "0px",
+ duration);
+ } else {
+ $sbt.css("left", -x / $v.width() * 100 + "%");
+ }
+ }
+ },
+
+ /**
+ * Handles window scrolling
+ * @private
+ * @param {number} y
+ * @param {number} scroll_height
+ */
+ _outerScroll: function ( y, scroll_height ) {
+ var self = this,
+ top = $( window ).scrollTop() - window.screenTop,
+ sy = 0,
+ duration = this.options.snapbackDuration,
+ start = getCurrentTime(),
+ tfunc;
+
+ if ( !this.options.outerScrollEnable ) {
+ return;
+ }
+
+ if ( this._$clip.jqmData("scroll") !== "y" ) {
+ return;
+ }
+
+ if ( this._outerScrolling ) {
+ return;
+ }
+
+ if ( y > 0 ) {
+ sy = ( window.screenTop ? window.screenTop : -y );
+ } else if ( y < -scroll_height ) {
+ sy = -y - scroll_height;
+ } else {
+ return;
+ }
+
+ tfunc = function () {
+ var elapsed = getCurrentTime() - start;
+
+ if ( elapsed >= duration ) {
+ window.scrollTo( 0, top + sy );
+ self._outerScrolling = undefined;
+
+ self._stopMScroll();
+ } else {
+ ec = $.easing.easeOutQuad( elapsed / duration,
+ elapsed, 0, 1, duration );
+
+ window.scrollTo( 0, top + ( sy * ec ) );
+ self._outerScrolling = setTimeout( tfunc, self._timerInterval );
+ }
+ };
+ this._outerScrolling = setTimeout( tfunc, self._timerInterval );
+ },
+
+ /**
+ * Scrolls to specified position with easeOutQuad calculations
+ * @private
+ * @param {number} x
+ * @param {number} y
+ * @param {number} duration
+ */
+ _scrollTo: function ( x, y, duration ) {
+ var self = this,
+ start = getCurrentTime(),
+ efunc = $.easing.easeOutQuad,
+ sx = this._sx,
+ sy = this._sy,
+ dx = x - sx,
+ dy = y - sy,
+ tfunc;
+
+ x = -x;
+ y = -y;
+
+ tfunc = function () {
+ var elapsed = getCurrentTime() - start,
+ ec;
+
+ if ( elapsed >= duration ) {
+ self._timerID = 0;
+ self._setScrollPosition( x, y );
+ } else {
+ ec = efunc( elapsed / duration, elapsed, 0, 1, duration );
+
+ self._setScrollPosition( sx + ( dx * ec ), sy + ( dy * ec ) );
+ self._timerID = setTimeout( tfunc, self._timerInterval );
+ }
+ };
+
+ this._timerID = setTimeout( tfunc, this._timerInterval );
+ },
+
+ /**
+ * Scrolls to specified position
+ * If scroll method is css translation or duration is a
+ * falsy value, the position is changed via translation,
+ * otherwise it's animated to that position
+ * @param {number} x
+ * @param {number} y
+ * @param {number} duration
+ */
+ scrollTo: function ( x, y, duration ) {
+ this._stopMScroll();
+ this._didDrag = false;
+
+ if ( !duration || this.options.scrollMethod === "translate" ) {
+ this._setScrollPosition( x, y, duration );
+ } else {
+ this._scrollTo( x, y, duration );
+ }
+ },
+
+ /**
+ * Centers scroll to view the specified child element
+ * @param {Element|jQuery} target
+ */
+ centerToElement: function ( element ) {
+ var $clip = this._$clip,
+ $view = this._$view,
+ $element = element.get ? element : $( element ),
+ delta = ( $clip.height() / 2 ) - ( element.height() / 2 ),
+ elementPosition = element.position().top;
+
+ element.parentsUntil( $view ).each( function () {
+ var $parent = $( this );
+ elementPosition += ( $parent.position().top + parseFloat( $parent.css( "marginTop" ) ) + parseFloat( $parent.css( "paddingTop" ) ) );
+ });
+
+ this.scrollTo( this._sx, -( elementPosition - delta ) );
+ },
+
+ /**
+ * Checks if the specified child element is visible
+ * and centers the scroll on it if it's not visible
+ * @param {Element|jQuery}
+ */
+ ensureElementIsVisible: function ( element ) {
+ var $element = element.get ? element : $( element ),
+ $clip = this._$clip,
+ clipHeight = $clip.height(),
+ clipTop = $clip.offset().top,
+ clipBottom = clipTop + clipHeight,
+ elementHeight = $element.height(),
+ elementTop = $element.offset().top,
+ elementBottom = elementTop + elementHeight,
+ elementFits = clipHeight > elementHeight,
+ $anchor,
+ anchorPosition = 0,
+ findPositionAnchor = function ( input ) {
+ var $label,
+ id = input.attr( "id" );
+ if ( input.is( ":input" ) && id ) {
+ $label = input.siblings( "label[for=" + id + "]" );
+ if ( $label.length > 0 ) {
+ return $label.eq( 0 );
+ }
+ }
+ return input;
+ };
+
+ switch( true ) {
+ case elementFits && clipTop < elementTop && clipBottom > elementBottom: // element fits in view is inside clip area
+ // pass, element position is ok
+ break;
+ case elementFits && clipTop < elementTop && clipBottom < elementBottom: // element fits in view but its visible only at top
+ case elementFits && clipTop > elementTop && clipBottom > elementBottom: // element fits in view but its visible only at bottom
+ case elementFits: // element fits in view but is not visible
+ this.centerToElement(element);
+ break;
+ case clipTop < elementTop && clipBottom < elementBottom: // element visible only at top
+ case clipTop > elementTop && clipBottom > elementBottom: // element visible only at bottom
+ // pass, we cant do anything, if we move the scroll
+ // the user could lost view of something he scrolled to
+ break;
+ default: // element is not visible
+ $anchor = findPositionAnchor( $element );
+ anchorPosition = $anchor.position().top + parseFloat( $anchor.css("marginTop" ) );
+ $anchor.parentsUntil($view).each(function () {
+ var $p = $( this );
+ anchorPosition += ( $p.position().top + parseFloat( $p.css("marginTop" ) ) );
+ });
+ this.scrollTo( self._sx, -anchorPosition );
+ break;
+ }
+ },
+
+ /**
+ * Returns current scroll position {x,y}
+ * @return {Object}
+ */
+ getScrollPosition: function () {
+ return { x: -this._sx, y: -this._sy };
+ },
+
+ /**
+ * Skipps dragging
+ * @param {Boolean}
+ */
+ skipDragging: function ( value ) {
+ this._skip_dragging = value;
+ },
+
+ /**
+ * Returns scroll hierarchy in an array of elements
+ * @private
+ * @return {Array}
+ */
+ _getScrollHierarchy: function () {
+ var svh = [],
+ d;
+
+ this._$clip.parents( ".ui-scrollview-clip").each( function () {
+ d = $( this ).jqmData("scrollview");
+ if ( d ) {
+ svh.unshift( d );
+ }
+ } );
+ return svh;
+ },
+
+ /**
+ * Returns ancestor for specified direction
+ * @private
+ * @param {string} dir
+ */
+ _getAncestorByDirection: function ( dir ) {
+ var svh = this._getScrollHierarchy(),
+ n = svh.length,
+ sv,
+ svdir;
+
+ while ( 0 < n-- ) {
+ sv = svh[n];
+ svdir = sv.options.direction;
+
+ if (!svdir || svdir === dir) {
+ return sv;
+ }
+ }
+ return null;
+ },
+
+ /**
+ * Handles dragstart event
+ * @private
+ * @param {Event} e
+ * @param {number} ex Event x position
+ * @param {number} ey Event y position
+ */
+ _handleDragStart: function ( e, ex, ey ) {
+ this._stopMScroll();
+
+ this._didDrag = false;
+ this._skip_dragging = false;
+ this._clipHeight = this._$clip.height();
+ var target = $( e.target ),
+ self = this,
+ $c = this._$clip,
+ svdir = this.options.direction;
+
+ /* should prevent the default behavior when click the button */
+ this._is_button = target.is( '.ui-btn' ) ||
+ target.is( '.ui-btn-text' ) ||
+ target.is( '.ui-btn-inner' ) ||
+ target.is( '.ui-btn-inner .ui-icon' );
+
+ /* should prevent the default behavior when click the slider */
+ if ( target.parents('.ui-slider').length || target.is('.ui-slider') ) {
+ this._skip_dragging = true;
+ return;
+ }
+
+ if ( target.is('textarea') ) {
+ target.bind( "scroll", function () {
+ self._skip_dragging = true;
+ target.unbind("scroll");
+ });
+ }
+
+ /*
+ * We need to prevent the default behavior to
+ * suppress accidental selection of text, etc.
+ */
+ this._is_inputbox = target.is(':input') ||
+ target.parents(':input').length > 0;
+
+ if ( this._is_inputbox ) {
+ target.one( "resize.scrollview", function () {
+ if ( ey > $c.height() ) {
+ self.scrollTo( -ex, self._sy - ey + $c.height(),
+ self.options.snapbackDuration );
+ }
+ });
+ }
+
+ if ( this.options.eventType === "mouse" && !this._is_inputbox && !this._is_button ) {
+ e.preventDefault();
+ }
+
+ this._lastX = ex;
+ this._lastY = ey;
+ this._startY = ey;
+ this._doSnapBackX = false;
+ this._doSnapBackY = false;
+ this._speedX = 0;
+ this._speedY = 0;
+ this._directionLock = "";
+
+ this._lastMove = 0;
+ this._enableTracking();
+
+ this._set_scrollbar_size();
+ },
+
+ /**
+ * Propagates dragging
+ * @private
+ * @param {jQuery} sv
+ * @param {Event} e
+ * @param {number} ex
+ * @param {number} ey
+ * @param {string} dir
+ */
+ _propagateDragMove: function ( sv, e, ex, ey, dir ) {
+ this._hideScrollBars();
+ this._hideOverflowIndicator();
+ this._disableTracking();
+ sv._handleDragStart( e, ex, ey );
+ sv._directionLock = dir;
+ sv._didDrag = this._didDrag;
+ },
+
+ /**
+ * Handles drag event
+ * @private
+ * @param {Event}
+ * @param {number} ex
+ * @param {number} ey
+ * @return {boolean|undefined}
+ */
+ _handleDragMove: function ( e, ex, ey ) {
+ this._moveInterval = ey;
+ if ( this._skip_dragging ) {
+ return;
+ }
+
+ if ( !this._dragging ) {
+ return;
+ }
+
+ if ( !this._is_inputbox && !this._is_button ) {
+ e.preventDefault();
+ }
+
+ var mt = this.options.moveThreshold,
+ dx = ex - this._lastX,
+ dy = ey - this._lastY,
+ svdir = this.options.direction,
+ dir = null,
+ x,
+ y,
+ sv,
+ scope,
+ newX,
+ newY,
+ dirLock;
+
+ this._lastMove = getCurrentTime();
+
+ if ( !this._directionLock ) {
+ x = Math.abs( dx );
+ y = Math.abs( dy );
+
+ if ( x < mt && y < mt ) {
+ return false;
+ }
+
+ if ( x < y && (x / y) < 0.5 ) {
+ dir = "y";
+ } else if ( x > y && (y / x) < 0.5 ) {
+ dir = "x";
+ }
+
+ if ( svdir && dir && svdir !== dir ) {
+ /*
+ * This scrollview can't handle the direction the user
+ * is attempting to scroll. Find an ancestor scrollview
+ * that can handle the request.
+ */
+
+ sv = this._getAncestorByDirection( dir );
+ if ( sv ) {
+ this._propagateDragMove( sv, e, ex, ey, dir );
+ return false;
+ }
+ }
+
+ this._directionLock = svdir || (dir || "none");
+ }
+
+ newX = this._sx;
+ newY = this._sy;
+ dirLock = this._directionLock;
+
+ if ( dirLock !== "y" && this._hTracker ) {
+ x = this._sx;
+ this._speedX = dx;
+ newX = x + dx;
+
+ this._doSnapBackX = false;
+
+ scope = ( newX > 0 || newX < this._maxX );
+
+ if ( scope && dirLock === "x" ) {
+ sv = this._getAncestorByDirection("x");
+ if ( sv ) {
+ this._setScrollPosition( newX > 0 ?
+ 0 : this._maxX, newY );
+ this._propagateDragMove( sv, e, ex, ey, dir );
+ return false;
+ }
+
+ newX = x + ( dx / 2 );
+ this._doSnapBackX = true;
+ }
+ }
+
+ if ( dirLock !== "x" && this._vTracker ) {
+ if ( Math.abs( this._startY - ey ) < mt && dirLock !== "xy" && this._didDrag === false ) {
+ return;
+ }
+
+ y = this._sy;
+ this._speedY = dy;
+ newY = y + dy;
+
+ this._doSnapBackY = false;
+
+ scope = ( newY > 0 || newY < this._maxY );
+
+ if ( scope && dirLock === "y" ) {
+ sv = this._getAncestorByDirection("y");
+ if ( sv ) {
+ this._setScrollPosition( newX,
+ newY > 0 ? 0 : this._maxY );
+ this._propagateDragMove( sv, e, ex, ey, dir );
+ return false;
+ }
+
+ newY = y + ( dy / 2 );
+ this._doSnapBackY = true;
+ }
+ }
+
+ if ( this.options.overshootEnable === false ) {
+ this._doSnapBackX = false;
+ this._doSnapBackY = false;
+ }
+
+ this._lastX = ex;
+ this._lastY = ey;
+
+ this._setScrollPosition( newX, newY );
+
+ if ( this._didDrag === false ) {
+ this._didDrag = true;
+ this._showScrollBars();
+ this._showOverflowIndicator();
+
+ this._$clip.parents(".ui-scrollview-clip").each( function () {
+ $( this ).scrollview( "skipDragging", true );
+ } );
+ }
+ },
+
+ /**
+ * Handles drag stop event, and returns drag status
+ * @param {Event} e
+ * @return {Boolean|undefined}
+ */
+ _handleDragStop: function ( e ) {
+ var self = this;
+
+ if ( this._skip_dragging ) {
+ return;
+ }
+
+ var l = this._lastMove,
+ t = getCurrentTime(),
+ doScroll = (l && (t - l) <= this.options.moveIntervalThreshold),
+ sx = ( this._hTracker && this._speedX && doScroll ) ?
+ this._speedX : ( this._doSnapBackX ? 1 : 0 ),
+ sy = ( this._vTracker && this._speedY && doScroll ) ?
+ this._speedY : ( this._doSnapBackY ? 1 : 0 ),
+ svdir = this.options.direction,
+ x,
+ y;
+
+ if ( sx || sy ) {
+ if ( !this._setGestureScroll( sx, sy ) ) {
+ this._startMScroll( sx, sy );
+ }
+ } else {
+ this._hideScrollBars();
+ this._hideOverflowIndicator();
+ }
+
+ this._disableTracking();
+
+ if ( this._endEffect ) {
+ setTimeout( function () {
+ self._setEndEffect( "out" );
+ self._hideScrollBars();
+ self._hideOverflowIndicator();
+ }, 300 );
+ }
+
+ return !this._didDrag;
+ },
+
+ /**
+ * Detects gestures and sets proper gesture direction
+ * @private
+ * @param {number} sx
+ * @param {number} sy
+ * @return {boolean}
+ */
+ _setGestureScroll: function ( sx, sy ) {
+ var self = this,
+ reset = function () {
+ clearTimeout( self._gesture_timer );
+ self._gesture_dir = 0;
+ self._gesture_timer = undefined;
+ },
+ direction = {
+ top: 0,
+ bottom: 1,
+ left: 2,
+ right: 3
+ };
+
+ if ( !sy && !sx ) {
+ return false;
+ }
+
+ if ( Math.abs( sx ) > Math.abs( sy ) ) {
+ dir = sx > 0 ? direction.left : direction.right;
+ } else {
+ dir = sy > 0 ? direction.top : direction.bottom;
+ }
+
+ if ( !this._gesture_timer ) {
+ this._gesture_dir = dir;
+
+ this._gesture_timer = setTimeout( function () {
+ reset();
+ }, 1000 );
+
+ return false;
+ }
+
+ if ( this._gesture_dir !== dir ) {
+ reset();
+ return false;
+ }
+
+ return false;
+ },
+
+ /**
+ * Enables dragging
+ * @private
+ */
+ _enableTracking: function () {
+ this._dragging = true;
+ },
+
+ /**
+ * Disables dragging
+ * @private
+ */
+ _disableTracking: function () {
+ this._dragging = false;
+ },
+
+ /**
+ * Shows scrollbars
+ * When interval is specified, the scrollbars will be
+ * hidden after the specified time in miliseconds
+ * @private
+ * @param {number} [interval]
+ */
+ _showScrollBars: function ( interval ) {
+ var vclass = "ui-scrollbar-visible",
+ self = this;
+
+ if ( !this.options.showScrollBars ) {
+ return;
+ }
+ if ( this._scrollbar_showed ) {
+ return;
+ }
+
+ if ( this._$vScrollBar ) {
+ this._$vScrollBar.addClass( vclass );
+ }
+ if ( this._$hScrollBar ) {
+ this._$hScrollBar.addClass( vclass );
+ }
+
+ this._scrollbar_showed = true;
+
+ if ( interval ) {
+ setTimeout( function () {
+ self._hideScrollBars();
+ }, interval );
+ }
+ },
+
+ /**
+ * Hides scrollbars
+ * @private
+ */
+ _hideScrollBars: function () {
+ var vclass = "ui-scrollbar-visible";
+
+ if ( !this.options.showScrollBars ) {
+ return;
+ }
+ if ( !this._scrollbar_showed ) {
+ return;
+ }
+
+ if ( this._$vScrollBar ) {
+ this._$vScrollBar.removeClass( vclass );
+ }
+ if ( this._$hScrollBar ) {
+ this._$hScrollBar.removeClass( vclass );
+ }
+
+ this._scrollbar_showed = false;
+ },
+
+ /**
+ * Sets opacities for the oveflow indicator
+ * according to specified direction. The direction
+ * is optional. Specify 1 for top, 0 for bottom, and
+ * a falsy value for both
+ * @private
+ * @param {number} [dir] 0
+ */
+ _setOverflowIndicator: function ( dir ) {
+ if ( dir === 1 ) {
+ this._display_indicator_top = "none";
+ this._display_indicator_bottom = "block";
+ } else if ( dir === 0 ) {
+ this._display_indicator_top = "block";
+ this._display_indicator_bottom = "none";
+ } else {
+ this._display_indicator_top = "block";
+ this._display_indicator_bottom = "block";
+ }
+ },
+
+ /**
+ * Display overflow indicator
+ * @private
+ */
+ _showOverflowIndicator: function () {
+ if ( !$( this.element ).is( ".ui-content" ) ) {
+ return true;
+ }
+
+ if ( !this.options.overflowEnable || !this._overflowAvail || this._softkeyboard ) {
+ return;
+ }
+
+ this._overflow_top.css( "display", this._display_indicator_top );
+ this._overflow_bottom.css( "display", this._display_indicator_bottom );
+
+ this._overflow_showed = true;
+ },
+
+ /**
+ * Hide overflow indicator
+ * @private
+ */
+ _hideOverflowIndicator: function () {
+ if ( !this.options.overflowEnable || !this._overflowAvail || this._softkeyboard ) {
+ return;
+ }
+
+ if ( this._overflow_showed === false ) {
+ return;
+ }
+
+ this._overflow_top.css( "display", "none" );
+ this._overflow_bottom.css( "display", "none" );
+
+ this._overflow_showed = false;
+ this._setOverflowIndicator();
+ },
+
+ /**
+ * Bind events
+ * @private
+ * @return {boolean|undefined}
+ */
+ _add_event: function () {
+ var self = this,
+ $c = this._$clip,
+ $v = this._$view;
+
+ if ( this.options.eventType === "mouse" ) {
+ this._dragEvt = "mousedown mousemove mouseup click mousewheel";
+
+ this._dragCB = function ( e ) {
+ switch ( e.type ) {
+ case "mousedown":
+ return self._handleDragStart( e,
+ e.clientX, e.clientY );
+
+ case "mousemove":
+ return self._handleDragMove( e,
+ e.clientX, e.clientY );
+
+ case "mouseup":
+ return self._handleDragStop( e );
+
+ case "click":
+ return !self._didDrag;
+
+ case "mousewheel":
+ var old = self.getScrollPosition();
+ self.scrollTo( -old.x,
+ -(old.y - e.originalEvent.wheelDelta) );
+ break;
+ }
+ };
+ } else {
+ this._dragEvt = "touchstart touchmove touchend";
+ var _in_progress = false;
+ this._dragCB = function ( e ) {
+ var touches = e.originalEvent.touches;
+
+ switch ( e.type ) {
+ case "touchstart":
+ if ( touches.length != 1 || _in_progress ) {
+ return;
+ }
+
+ _in_progress = true;
+
+ return self._handleDragStart( e,
+ touches[0].pageX, touches[0].pageY );
+
+ case "touchmove":
+ if ( !_in_progress || touches.length != 1) {
+ return;
+ }
+
+ return self._handleDragMove( e,
+ touches[0].pageX, touches[0].pageY );
+
+ case "touchend":
+ if ( !_in_progress ) {
+ return;
+ }
+
+ _in_progress = false;
+
+ if ( touches.length != 0 ) {
+ return;
+ }
+
+ return self._handleDragStop( e );
+ }
+ };
+ };
+
+ $v.bind( this._dragEvt, this._dragCB );
+
+ // N_SE-35696 / N_SE-35800
+ var clipScrollDelta = 0,
+ clipScrollLast = 0;
+ $c.on( "scroll", function () {
+ var clipScrollTop = $c.scrollTop(),
+ currentPositon = self.getScrollPosition(),
+ inputs;
+
+ clipScrollDelta = clipScrollTop - clipScrollLast;
+ clipScrollLast = clipScrollTop;
+
+ if ( clipScrollDelta > 0 ) {
+ inputs = $v.find( ":input.ui-focus" );
+ $c.scrollTop( 0 );
+ if ( inputs.length ) {
+ // CHECK WHERE WE ARE IN THE INPUTS
+ clipScrollDelta = 0;
+ }
+ self.scrollTo( -currentPositon.x, -( currentPositon.y + clipScrollDelta ) );
+ }
+ } );
+
+ $v.bind( "keydown", function ( e ) {
+ var $focusedElement;
+
+ if ( e.keyCode == 9 ) {
+ return false;
+ }
+
+ $focusedElement = $c.find( ".ui-focus" );
+ if ( !$focusedElement.length ) {
+ return;
+ }
+ self.ensureElementIsVisible( $focusedElement );
+
+ return;
+ });
+
+ $v.bind( "keyup", function ( e ) {
+ var $input;
+
+ if ( e.keyCode !== 9 ) {
+ return;
+ }
+
+ /* Tab Key */
+ $input = $( this ).find( ":input.ui-focus" ).eq( 0 );
+ if ( !$input ) {
+ return;
+ }
+ self.ensureElementIsVisible( $input );
+ $input.focus();
+
+ return false;
+ });
+
+ $c.bind( "updatelayout", function ( e ) {
+ var sy,
+ vh,
+ view_h = self._getViewHeight();
+
+ if ( !$c.height() || !view_h ) {
+ self.scrollTo( 0, 0, 0 );
+ return;
+ }
+
+ sy = $c.height() - view_h;
+ vh = view_h - self._view_height;
+
+ self._view_height = view_h;
+
+ if ( vh == 0 || vh > $c.height() / 2 ) {
+ return;
+ }
+
+ if ( sy > 0 ) {
+ self.scrollTo( 0, 0, 0 );
+ } else if ( self._sy - sy <= -vh ) {
+ self.scrollTo( 0, self._sy,
+ self.options.snapbackDuration );
+ } else if ( self._sy - sy <= vh + self.options.moveThreshold ) {
+ self.scrollTo( 0, sy,
+ self.options.snapbackDuration );
+ }
+ });
+
+ $( window ).bind( "resize", function ( e ) {
+ var focused,
+ view_h = self._getViewHeight();
+
+ if ( $(".ui-page-active").get(0) !== $c.closest(".ui-page").get(0) ) {
+ return;
+ }
+
+ if ( !$c.height() || !view_h ) {
+ return;
+ }
+
+ focused = $c.find(".ui-focus");
+
+ if ( focused ) {
+ focused.trigger("resize.scrollview");
+ }
+
+ /* calibration - after triggered throttledresize */
+ setTimeout( function () {
+ var view_w = $v.outerWidth(),
+ cw = $c.outerWidth(),
+ scroll_x,
+ scroll_y;
+ if ( self._sy < $c.height() - self._getViewHeight() ) {
+ scroll_y = $c.height() - self._getViewHeight();
+ scroll_x = 0;
+ }
+ if ( self._sx < cw - view_w ) {
+ scroll_x = cw - view_w;
+ scroll_y = scroll_y || 0;
+ }
+ if (scroll_x || scroll_y) {
+ self.scrollTo( scroll_x, scroll_y, self.options.overshootDuration );
+ }
+ }, 260 );
+
+ self._view_height = view_h;
+ self._clipHeight = self._$clip.height();
+ });
+
+ $( window ).bind( "vmouseout", function ( e ) {
+ var drag_stop = false;
+
+ if ( $(".ui-page-active").get(0) !== $c.closest(".ui-page").get(0) ) {
+ return;
+ }
+
+ if ( !self._dragging ) {
+ return;
+ }
+
+ if ( e.pageX < 0 || e.pageX > $( window ).width() ) {
+ drag_stop = true;
+ }
+
+ if ( e.pageY < 0 || e.pageY > $( window ).height() ) {
+ drag_stop = true;
+ }
+
+ if ( drag_stop ) {
+ self._hideScrollBars();
+ self._hideOverflowIndicator();
+ self._disableTracking();
+ }
+ });
+
+ this._softkeyboard = false;
+ this._softkeyboardHeight = 0;
+
+ window.addEventListener( "softkeyboardchange", function ( e ) {
+ if ( $(".ui-page-active").get(0) !== $c.closest(".ui-page").get(0) ) {
+ return;
+ }
+
+ self._softkeyboard = ( e.state === "on" ? true : false );
+ self._softkeyboardHeight = parseInt( e.height ) *
+ ( $( window ).width() / window.screen.availWidth );
+ });
+
+ $c.closest(".ui-page")
+ .bind( "pageshow", function ( e ) {
+ self._view_height = self._$view.height();
+
+ /* should be called after pagelayout */
+ setTimeout( function () {
+ self._view_height = self._getViewHeight();
+ self._set_scrollbar_size();
+ self._setScrollPosition( self._sx, self._sy );
+ self._showScrollBars( 2000 );
+ }, 0 );
+ });
+
+ $c.closest(".ui-page").find( ".ui-popup" )
+ .bind( "popupafteropen", function ( e ) {
+ if ( !$( self.element ).parents().is( ".ui-ctxpopup" ) ) {
+ return true;
+ }
+
+ setTimeout( function () {
+ self._setScrollPosition( self._sx, self._sy );
+ self._showScrollBars( 2000 );
+ }, 0 );
+ });
+ },
+
+ /**
+ * Adds scrollbar elements to DOM
+ * @private
+ */
+ _add_scrollbar: function () {
+ var $c = this._$clip,
+ prefix = "<div class=\"ui-scrollbar ui-scrollbar-",
+ suffix = "\"><div class=\"ui-scrollbar-track\"><div class=\"ui-scrollbar-thumb\"></div></div></div>";
+
+ if ( !this.options.showScrollBars ) {
+ return;
+ }
+
+ if ( this._vTracker ) {
+ $c.append( prefix + "y" + suffix );
+ this._$vScrollBar = $c.children(".ui-scrollbar-y");
+ }
+ if ( this._hTracker ) {
+ $c.append( prefix + "x" + suffix );
+ this._$hScrollBar = $c.children(".ui-scrollbar-x");
+ }
+
+ this._scrollbar_showed = false;
+ },
+
+ /**
+ * Adds scroll jump button to DOM
+ * @private
+ */
+ _add_scroll_jump: function () {
+ var $c = this._$clip,
+ self = this,
+ top_btn,
+ left_btn;
+
+ if ( !this.options.scrollJump ) {
+ return;
+ }
+
+ if ( this._vTracker ) {
+ top_btn = $( '<div class="ui-scroll-jump-top-bg">' +
+ '<div data-role="button" data-inline="true" data-icon="scrolltop" data-style="box"></div></div>' );
+ $c.append( top_btn ).trigger("create");
+
+ top_btn.bind( "vclick", function () {
+ self.scrollTo( 0, 0, self.options.overshootDuration );
+ } );
+ }
+
+ if ( this._hTracker ) {
+ left_btn = $( '<div class="ui-scroll-jump-left-bg">' +
+ '<div data-role="button" data-inline="true" data-icon="scrollleft" data-style="box"></div></div>' );
+ $c.append( left_btn ).trigger("create");
+
+ left_btn.bind( "vclick", function () {
+ self.scrollTo( 0, 0, self.options.overshootDuration );
+ } );
+ }
+ },
+
+ /**
+ * Adds overflow indicator to DOM
+ * @private
+ */
+ _add_overflow_indicator: function () {
+ if ( !this.options.overflowEnable ) {
+ return;
+ }
+
+ this._overflow_top = $( '<div class="ui-overflow-indicator-top"></div>' );
+ this._overflow_bottom = $( '<div class="ui-overflow-indicator-bottom"></div>' );
+
+ this._$clip.append( this._overflow_top );
+ this._$clip.append( this._overflow_bottom );
+
+ this._display_indicator_top = "block";
+ this._display_indicator_bottom = "block";
+ this._overflow_showed = false;
+ },
+
+ /**
+ * Sets the size of the scrollbars
+ * @private
+ */
+ _set_scrollbar_size: function () {
+ var $c = this._$clip,
+ $v = this._$view,
+ cw = 0,
+ vw = 0,
+ ch = 0,
+ vh = 0,
+ thumb;
+
+ if ( !this.options.showScrollBars ) {
+ return;
+ }
+
+ if ( this._hTracker ) {
+ cw = $c.width();
+ vw = $v.width();
+ this._maxX = cw - vw;
+
+ if ( this._maxX > 0 ) {
+ this._maxX = 0;
+ }
+ if ( this._$hScrollBar && vw ) {
+ thumb = this._$hScrollBar.find(".ui-scrollbar-thumb");
+ thumb.css( "width", (cw >= vw ? "0" :
+ (Math.floor(cw / vw * 100) || 1) + "%") );
+ }
+ }
+
+ if ( this._vTracker ) {
+ ch = $c.height();
+ vh = this._getViewHeight();
+ this._maxY = ch - vh;
+
+ if ( this._maxY > 0 || vh === 0 ) {
+ this._maxY = 0;
+ }
+ if ( ( this._$vScrollBar && vh ) || vh === 0 ) {
+ thumb = this._$vScrollBar.find(".ui-scrollbar-thumb");
+ thumb.css( "height", (ch >= vh ? "0" :
+ (Math.floor(ch / vh * 100) || 1) + "%") );
+
+ this._overflowAvail = !!thumb.height();
+ }
+ }
+ }
+ });
+
+ /**
+ * Momentum tracker
+ */
+ $.extend( MomentumTracker.prototype, {
+ /**
+ * Starts momentum callculations
+ * @param {number} pos
+ * @param {number} speed
+ * @param {number} duration
+ * @param {number} minPos
+ * @param {number} maxPos
+ */
+ start: function ( pos, speed, duration, minPos, maxPos ) {
+ var tstate = ( pos < minPos || pos > maxPos ) ?
+ tstates.snapback : tstates.scrolling,
+ pos_temp;
+
+ this.state = ( speed !== 0 ) ? tstate : tstates.done;
+ this.pos = pos;
+ this.speed = speed;
+ this.duration = ( this.state === tstates.snapback ) ?
+ this.options.snapbackDuration : duration;
+ this.minPos = minPos;
+ this.maxPos = maxPos;
+
+ this.fromPos = ( this.state === tstates.snapback ) ? this.pos : 0;
+ pos_temp = ( this.pos < this.minPos ) ? this.minPos : this.maxPos;
+ this.toPos = ( this.state === tstates.snapback ) ? pos_temp : 0;
+
+ this.startTime = getCurrentTime();
+ },
+
+ /**
+ * Resets momentum tracker calculations and sets
+ * state to done
+ */
+ reset: function () {
+ this.state = tstates.done;
+ this.pos = 0;
+ this.speed = 0;
+ this.minPos = 0;
+ this.maxPos = 0;
+ this.duration = 0;
+ this.remained = 0;
+ },
+
+ /**
+ * Recalculate momentum tracker estimates
+ * @param {boolean} overshootEnable
+ * @return {number} position
+ */
+ update: function ( overshootEnable ) {
+ var state = this.state,
+ cur_time = getCurrentTime(),
+ duration = this.duration,
+ elapsed = cur_time - this.startTime,
+ dx,
+ x,
+ didOverShoot;
+
+ if ( state === tstates.done ) {
+ return this.pos;
+ }
+
+ elapsed = elapsed > duration ? duration : elapsed;
+
+ this.remained = duration - elapsed;
+
+ if ( state === tstates.scrolling || state === tstates.overshot ) {
+ dx = this.speed *
+ ( 1 - $.easing[this.easing]( elapsed / duration,
+ elapsed, 0, 1, duration ) );
+
+ x = this.pos + dx;
+
+ didOverShoot = ( state === tstates.scrolling ) &&
+ ( x < this.minPos || x > this.maxPos );
+
+ if ( didOverShoot ) {
+ x = ( x < this.minPos ) ? this.minPos : this.maxPos;
+ }
+
+ this.pos = x;
+
+ if ( state === tstates.overshot ) {
+ if ( !overshootEnable ) {
+ this.state = tstates.done;
+ }
+ if ( elapsed >= duration ) {
+ this.state = tstates.snapback;
+ this.fromPos = this.pos;
+ this.toPos = ( x < this.minPos ) ?
+ this.minPos : this.maxPos;
+ this.duration = this.options.snapbackDuration;
+ this.startTime = cur_time;
+ elapsed = 0;
+ }
+ } else if ( state === tstates.scrolling ) {
+ if ( didOverShoot && overshootEnable ) {
+ this.state = tstates.overshot;
+ this.speed = dx / 2;
+ this.duration = this.options.overshootDuration;
+ this.startTime = cur_time;
+ } else if ( elapsed >= duration ) {
+ this.state = tstates.done;
+ }
+ }
+ } else if ( state === tstates.snapback ) {
+ if ( elapsed >= duration ) {
+ this.pos = this.toPos;
+ this.state = tstates.done;
+ } else {
+ this.pos = this.fromPos + (( this.toPos - this.fromPos ) *
+ $.easing[this.easing]( elapsed / duration,
+ elapsed, 0, 1, duration ));
+ }
+ }
+
+ return this.pos;
+ },
+
+ /**
+ * Checks if momentum state is done
+ * @return {boolean}
+ */
+ done: function () {
+ return this.state === tstates.done;
+ },
+
+ /**
+ * Checks if the position is minimal
+ * @return {boolean}
+ */
+ isMin: function () {
+ return this.pos === this.minPos;
+ },
+
+ /**
+ * Checks if the position is maximal
+ * @return {boolean}
+ */
+ isMax: function () {
+ return this.pos === this.maxPos;
+ },
+
+ /**
+ * Check if momentum tracking is available
+ * @return {boolean}
+ */
+ isAvail: function () {
+ return !( this.minPos === this.maxPos );
+ },
+
+ /**
+ * Returns remaining time
+ * @return {number}
+ */
+ getRemained: function () {
+ return this.remained;
+ },
+
+ /**
+ * Returns current position
+ * @return {number}
+ */
+ getPosition: function () {
+ return this.pos;
+ }
+ });
+
+ $( document ).bind( 'pagecreate create', function ( e ) {
+ var $page = $( e.target ),
+ content_scroll = $page.find(".ui-content").jqmData("scroll");
+
+ /* content scroll */
+ if ( $.support.scrollview === undefined ) {
+ $.support.scrollview = true;
+ }
+
+ if ( $.support.scrollview === true && content_scroll === undefined ) {
+ content_scroll = "y";
+ }
+
+ if ( content_scroll !== "y" ) {
+ content_scroll = "none";
+ }
+
+ $page.find(".ui-content").attr( "data-scroll", content_scroll );
+
+ $page.find(":jqmData(scroll)").not(".ui-scrollview-clip").each( function () {
+ if ( $( this ).hasClass("ui-scrolllistview") ) {
+ $( this ).scrolllistview();
+ } else {
+ var st = $( this ).jqmData("scroll"),
+ dir = st && ( st.search(/^[xy]/) !== -1 ) ? st : null,
+ content = $(this).hasClass("ui-content"),
+ opts;
+
+ if ( st === "none" ) {
+ return;
+ }
+
+ opts = {
+ direction: dir || undefined,
+ overflowEnable: content,
+ scrollMethod: $( this ).jqmData("scroll-method") || undefined,
+ scrollJump: $( this ).jqmData("scroll-jump") || undefined
+ };
+
+ $( this ).scrollview( opts );
+ }
+ });
+ });
+
+ $( document ).bind( 'pageshow', function ( e ) {
+ var $page = $( e.target ),
+ scroll = $page.find(".ui-content").jqmData("scroll");
+
+ if ( scroll === "y" ) {
+ resizePageContentHeight( e.target );
+ }
+ });
+
+}( jQuery, window, document ) );
+
+//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
+} );
+//>>excludeEnd("jqmBuildExclude");