Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

* First commit

  • Loading branch information...
commit 633c12500264e0b8c8b07e0adece9cafc81ac5b1 0 parents
@joehewitt authored
13 LICENSE
@@ -0,0 +1,13 @@
+Copyright 2011 Joe Hewitt
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+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.
38 README.md
@@ -0,0 +1,38 @@
+scrollability
+=============
+
+Give your mobile web apps a pretty darn good approximation of native scrolling.
+
+Scrollability is a single script, it's small, and it has no external dependencies. Drop it into your page, add a few CSS classes to scrollable elements, and scroll away.
+
+Status
+------
+
+This project is a WORK-IN-PROGRESS and is not yet ready to use. Stay tuned! Documentation will be written when the library is ready.
+
+Plan
+----
+
+As of this writing, Scrollability supports only basic vertical or horizontal scrolling. Future plans include:
+
+* Snapping to pages
+* Sticky table headers
+* Photo browser
+* More customization of the animation details
+
+License
+-------
+
+Copyright 2011 Joe Hewitt
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+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.
151 examples/example1.html
@@ -0,0 +1,151 @@
+<!doctype html>
+
+<html lang="en">
+<head>
+<title>Scrollability</title>
+<meta charset="utf-8"/>
+<meta name="viewport" content="width=device-width,maximum-scale=1.0" />
+<style type="text/css">
+
+html {
+ overflow: hidden;
+ background: #333;
+ font-family: Helvetica;
+}
+
+#container {
+ position: absolute;
+ left: 0;
+ top: 30px;
+ bottom: 0;
+ width: 320px;
+ background: #fff;
+ overflow: hidden;
+}
+
+#page {
+ -webkit-transform: translate3d(0,0,0);
+}
+
+.item {
+ position: relative;
+ top: -1px;
+ border-top: 1px solid #ccc;
+ padding: 8px 12px;
+ font: 21px Helvetica;
+ font-weight: bold;
+ background: #fff;
+}
+
+.item:last-child {
+ border-bottom: 1px solid #ccc;
+}
+
+.bar {
+ position: absolute;
+ background: #222;
+ left: 0;
+ top: 0;
+ width: 100%;
+ color: #fff;
+ padding: 7px 0;
+ text-align: center;
+ font-size: 12px;
+ font-weight: bold;
+ border-bottom: 1px solid #000;
+}
+
+.item.touched {
+ color: #fff;
+ background: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0, #028AF3),
+ color-stop(1, #005DE6)
+ );
+}
+
+</style>
+
+<script type="text/javascript" src="../scrollability-min.js"></script>
+
+<script language="javascript">
+
+var names = [
+"Arnulfo Heriberto Hao",
+"Elbert Murray Heartsill",
+"Danny Fred Querido",
+"Boris Hobert Cregger",
+"Clifton Brady Laurance",
+"Homer Jay Telch",
+"Lawrence Lloyd Barrus",
+"Shannon Isaias Plate",
+"Odis Raul Insley",
+"Marion Ben Nhatsavang",
+"Dong Brent Mcwilson",
+"Chong Jarrod Hinderman",
+"Eric Reyes Caffie",
+"Junior Newton Dagan",
+"Cleo Maynard Gutirrez",
+"Cruz Rey Misiewicz",
+"Jeremy Nelson Bew",
+"Doug Buster Maclead",
+"Zachariah Martin Colo",
+"Nathaniel Houston Berneri",
+"Clement Laverne Vrana",
+"Kermit Jeffery Left",
+"Davis Margarito Koran",
+"Booker Wallace Primavera",
+"Prince Enrique Pulice",
+"Johnathon Minh Inciong",
+"Stan Tony Calaycay",
+"Owen Sang Tugade",
+"Charlie Melvin Veloso",
+"August Galen Kathel",
+"Dominique Marc Sitterson",
+"Mitchell Isaiah Chareunrath",
+"Luther Avery Fekety",
+"Myles Doug Strohl",
+"Reuben Bob Holoman",
+"Eloy Erwin Kendrick",
+"Alec Bernard Hitz",
+"Jessie Oswaldo Shamir",
+"Jamison Seymour Nighman",
+"Garret Chester Robasciotti",
+"Clifford Samuel Sokoloff",
+"Carlton Jamel Mcentee",
+"Blair Titus Lennertz",
+"Barton Edmund Payn",
+"Ed Williams Faltin",
+"Leonardo Kent Trimarchi",
+"Lon Esteban Samrah",
+"Mike Alfonzo Alaniz",
+"George Gil Domnick",
+"Lemuel Lesley Cerventez",
+];
+
+addEventListener('DOMContentLoaded', function() {
+ var container = document.getElementById('container');
+ var page = document.getElementById('page');
+ for (var i = 0; i < names.length*5; ++i) {
+ var item = document.createElement('div');
+ item.className = 'item';
+ item.innerHTML = names[i%names.length];
+ page.appendChild(item);
+ if (page.offsetHeight > container.offsetHeight*8) {
+ break;
+ }
+ }
+});
+
+</script>
+
+</head>
+<body>
+ <div class="bar top">Scrollability Demo</div>
+ <div id="container">
+ <div id="page" class="scrollable vertical"></div>
+ </div>
+</body>
+</html>
1  scrollability-min.js
@@ -0,0 +1 @@
+/* See LICENSE for terms of usage */(function(){function F(b){var c=b.parentNode;return{node:b,scrollbar:C(b),min:-c.scrollHeight+c.offsetHeight,max:0,viewport:c.offsetHeight,bounce:c.offsetHeight*d,constrained:!0,filter:function(a,b){return b},disable:function(b,c,d,e){var f=Math.abs(b-d),g=Math.abs(c-e);if(f>g&&f>a)return!0},update:function(a,b){B(a,a.scrollable_horizontal,b)}}}function E(b){var c=b.parentNode;return{node:b,min:-c.scrollWidth+c.offsetWidth,max:0,viewport:c.offsetWidth,bounce:c.offsetWidth*d,constrained:!0,filter:function(a,b){return a},disable:function(b,c,d,e){var f=Math.abs(b-d),g=Math.abs(c-e);if(g>f&&g>a)return!0},update:function(a,b){B(a,b,a.scrollable_vertical)}}}function D(a,b,c,d){return a==d?b+c:c*(-Math.pow(2,-10*a/d)+1)+b}function C(a){if(!a.scrollableScrollbar){var b=a.scrollableScrollbar=document.createElement("div");b.className="scrollableScrollbar",b.style.cssText=["position: absolute","top: 0","right: 2px","width: 5px","min-height: 6px","background: #666","opacity: 0","-webkit-border-radius: 2px 3px","-webkit-transform: translate3d(0,0,0)","-webkit-transition: opacity 0.15s linear"].join(";")}return a.scrollableScrollbar}function B(a,b,c){a.style.webkitTransform="translate3d("+(b?Math.round(b)+"px":"0")+","+(c?Math.round(c)+"px":"0")+","+"0)"}function A(){if(r){clearInterval(r),r=0;for(var a=0;a<s.length;++a){var b=s[a];b.terminator()}s=[]}}function z(a){for(var b=0;b<a.length;++b){var c=a[b];c.className=c.className.replace("touched","")}}function y(a){var b=[];for(var c=a;c;c=c.parentNode)c.nodeType==1&&(c.className=(c.className?c.className+" ":"")+"touched",b.push(c));return b}function x(a){var b=[];while(a){if(a.nodeType==1){var c=a.className.split(" ");if(c.indexOf("scrollable")!=-1){var d=c.indexOf("paginated")!=-1;for(var e=0;e<c.length;++e){var f=c[e];if(t[f]){var g=t[f](a);g.key="scrollable_"+f,g.paginated=d,g.key in a||(a[g.key]=g.initial?g.initial(a):0),b.push(g)}}if(c.indexOf("exclusive")!=-1)break}}a=a.parentNode}return b}function w(){var a=(new Date).getTime();for(var b=0;b<s.length;++b){var c=s[b],d=c.filter(n,o);c.animator(d,a)||(c.terminator(),s.splice(b--,1))}s.length||A()}function v(a,d,h,l){function N(){n?M(Math.round(s/o)*o):s>u&&m?M(u):s<t&&m&&M(t),r&&(r.style.opacity="0",r.style.webkitTransition="opacity 0.2s linear")}function M(b,c){s=b,a.node[a.key]=s,a.update(a.node,s);var d=-t-u;if(r&&o<d){var e=o-k*2,f=e/d*e,g=0;s>u?(f=Math.max(f-(s-u),5),g=0):s<t?(f=Math.max(f-(t-s),5),g=e-f):g=Math.round(Math.abs(s)/d*(e-f)),g+=k,r.style.height=Math.round(f)+"px",B(r,0,g),q&&(r.style.opacity="0.8",r.style.webkitTransition="none")}return c}function L(a,d){var h=1/(d-G);G=d;var i=!0;if(p){var k=(a-F)*b;if(!k){H||(H=d);if(d-H<I)return!0}else H=0;F=a,x=k/h;if(s>u&&m){var l=s-u;x*=1-l/C}else if(s<t&&m){var l=t-s;x*=1-l/C}}else{if(n&&!J){J=!0;if(Math.abs(s-u)>E||Math.abs(x)>j)s>u?u!=w&&(u+=o,t+=o):t!=v&&(u-=o,t-=o)}if(s>u&&m){if(!(x>0)){y||(z=s,A=u-s),s=D(y,z,A,g);return M(s,++y<=g&&Math.floor(s)>u)}var l=s-u,q=1-l/C;x=Math.max(x-e*h,0)*q,y=0}else if(s<t&&m){if(!(x<0)){y||(z=s,A=t-s),s=D(y,z,A,g);return M(s,++y<=g&&Math.ceil(s)<t)}var l=t-s,q=1-l/C;x=Math.min(x+e*h,0)*q,y=0}else{y||(x<0&&x<-c?x=-c:x>0&&x>c&&(x=c),z=x),x=D(y,z,-z,f);if(++y>f||Math.floor(x)==0)i=!1}}s+=x*h;return M(s,i)}var m=a.constrained,n=a.paginated,o=a.viewport||0,r=a.scrollbar,s=a.node[a.key],t=a.min,u=a.max,v=t,w=Math.round(u/o)*o,x=0,y=0,z,A,C=a.bounce,E=o*i,F=a.filter(d,h),G=l,H=0,I=20,J=!1;if(n){var K=Math.round(s/o)*o;t=u=Math.round(K+w)}r&&a.node.parentNode.appendChild(r);return{filter:a.filter,disable:a.disable,animator:L,terminator:N}}function u(a){function t(a){d&&(clearTimeout(d),d=0);if(b){var c=document.createEvent("MouseEvents");c.initMouseEvent("click",!0,!0,window,1),b[0].dispatchEvent(c),z(b)}j.removeEventListener("touchmove",k,!1),j.removeEventListener("touchend",t,!1),p=!1}function k(a){a.preventDefault(),q=!0,d&&(clearTimeout(d),d=0),b&&(z(b),b=null);var c=a.touches[0];n=c.clientX,o=c.clientY;if(s.length>1)for(var e=0;e<s.length;++e){var f=s[e];if(f.disable&&f.disable(n,o,l,m)){f.terminator(),s.splice(e,1);break}}}a.preventDefault();var b=null,c=a.target,d=setTimeout(function(){d=0,b=y(c)},50);A();var e=a.touches[0];n=l=e.clientX,o=m=e.clientY,p=!0,q=!1,s=[];var f=(new Date).getTime(),g=x(a.target);if(g.length){for(var h=0;h<g.length;++h){var i=v(g[h],n,o,f);i&&s.push(i)}r=setInterval(w,0)}var j=document;j.addEventListener("touchmove",k,!1),j.addEventListener("touchend",t,!1)}var a=10,b=.6,c=1300,d=.5,e=300,f=350,g=90,h=60,i=.05,j=50,k=2,l,m,n,o,p,q,r=0,s=[],t={horizontal:E,vertical:F};document.addEventListener("touchstart",u,!1)})()
473 scrollability.js
@@ -0,0 +1,473 @@
+/* See LICENSE for terms of usage */
+(function() {
+
+var kLockThreshold = 10;
+var kTouchMultiplier = 0.6;
+var kMaxVelocity = 1300;
+var kBounceLimit = 0.5;
+var kBounceDecelRate = 300;
+var kDecelRate = 350;
+var kBounceTime = 90;
+var kScrollToTime = 60;
+var kPageLimit = 0.05;
+var kPageEscapeVelocity = 50;
+var kScrollbarMargin = 2;
+
+var startX, startY, touchX, touchY, touchDown, touchMoved;
+var animationInterval = 0;
+var touchTargets = [];
+
+var scrollers = {
+ 'horizontal': createXTarget,
+ 'vertical': createYTarget
+};
+
+function onTouchStart(event) {
+ event.preventDefault();
+
+ var touched = null;
+
+ var touchCandidate = event.target;
+ var holdTimeout = setTimeout(function() {
+ holdTimeout = 0;
+ touched = setTouched(touchCandidate);
+ }, 50);
+
+ stopAnimation();
+
+ var touch = event.touches[0];
+ touchX = startX = touch.clientX;
+ touchY = startY = touch.clientY;
+ touchDown = true;
+ touchMoved = false;
+ touchTargets = [];
+
+ var startTime = new Date().getTime();
+ var candidates = getTouchTargets(event.target);
+ if (candidates.length) {
+ for (var i = 0; i < candidates.length; ++i) {
+ var target = createTarget(candidates[i], touchX, touchY, startTime);
+ if (target) {
+ touchTargets.push(target);
+ }
+ }
+
+ animationInterval = setInterval(touchAnimation, 0);
+ }
+
+ var d = document;
+ d.addEventListener('touchmove', onTouchMove, false);
+ d.addEventListener('touchend', onTouchEnd, false);
+
+ function onTouchMove(event) {
+ event.preventDefault();
+ touchMoved = true;
+
+ if (holdTimeout) {
+ clearTimeout(holdTimeout);
+ holdTimeout = 0;
+ }
+ if (touched) {
+ releaseTouched(touched);
+ touched = null;
+ }
+ var touch = event.touches[0];
+ touchX = touch.clientX;
+ touchY = touch.clientY;
+
+ if (touchTargets.length > 1) {
+ for (var i = 0; i < touchTargets.length; ++i) {
+ var target = touchTargets[i];
+ if (target.disable && target.disable(touchX, touchY, startX, startY)) {
+ target.terminator();
+ touchTargets.splice(i, 1);
+ break;
+ }
+ }
+ }
+ }
+
+ function onTouchEnd(event) {
+ if (holdTimeout) {
+ clearTimeout(holdTimeout);
+ holdTimeout = 0;
+ }
+
+ if (touched) {
+ var evt = document.createEvent('MouseEvents');
+ evt.initMouseEvent('click', true, true, window, 1);
+ touched[0].dispatchEvent(evt);
+ releaseTouched(touched);
+ }
+
+ d.removeEventListener('touchmove', onTouchMove, false);
+ d.removeEventListener('touchend', onTouchEnd, false);
+ touchDown = false;
+ }
+}
+
+function createTarget(target, startX, startY, startTime) {
+ var constrained = target.constrained;
+ var paginated = target.paginated;
+ var viewport = target.viewport || 0;
+ var scrollbar = target.scrollbar;
+ var position = target.node[target.key];
+ var min = target.min;
+ var max = target.max;
+ var absMin = min;
+ var absMax = Math.round(max/viewport)*viewport;
+ var velocity = 0;
+ var decelerating = 0;
+ var decelOrigin, decelDelta;
+ var bounceLimit = target.bounce;
+ var pageLimit = viewport * kPageLimit;
+ var lastTouch = target.filter(startX, startY);
+ var lastTime = startTime;
+ var stillTime = 0;
+ var stillThreshold = 20;
+ var snapped = false;
+
+ if (paginated) {
+ var xposition = Math.round(position/viewport) * viewport;
+ min = max = Math.round(xposition + absMax);
+ }
+
+ if (scrollbar) {
+ target.node.parentNode.appendChild(scrollbar);
+ }
+
+ function animator(touch, time) {
+ var deltaTime = 1 / (time - lastTime);
+ lastTime = time;
+
+ var continues = true;
+ if (touchDown) {
+ var delta = (touch - lastTouch) * kTouchMultiplier;
+ if (!delta) {
+ // Heuristics to prevent out delta=0 changes from making velocity=0 and
+ // stopping all motion in its tracks. We need to distinguish when the finger
+ // has actuall stopped moving from when the timer fired too quickly.
+ if (!stillTime) {
+ stillTime = time;
+ }
+ if (time - stillTime < stillThreshold) {
+ return true;
+ }
+ } else {
+ stillTime = 0;
+ }
+
+ lastTouch = touch;
+ velocity = delta / deltaTime;
+
+ // Apply resistance along the edges
+ if (position > max && constrained) {
+ var excess = position - max;
+ velocity *= (1.0 - excess / bounceLimit);
+ } else if (position < min && constrained) {
+ var excess = min - position;
+ velocity *= (1.0 - excess / bounceLimit);
+ }
+ } else {
+ if (paginated && !snapped) {
+ // When finger is released, decide whether to jump to next/previous page
+ // or to snap back to the current page
+ snapped = true;
+ if (Math.abs(position - max) > pageLimit || Math.abs(velocity) > kPageEscapeVelocity) {
+ if (position > max) {
+ if (max != absMax) {
+ max += viewport;
+ min += viewport;
+ }
+ } else {
+ if (min != absMin) {
+ max -= viewport;
+ min -= viewport;
+ }
+ }
+ }
+ }
+
+ if (position > max && constrained) {
+ if (velocity > 0) {
+ // Slowing down
+ var excess = position - max;
+ var elasticity = (1.0 - excess / bounceLimit);
+ velocity = Math.max(velocity - kBounceDecelRate * deltaTime, 0) * elasticity;
+ decelerating = 0;
+ } else {
+ // Bouncing back
+ if (!decelerating) {
+ decelOrigin = position;
+ decelDelta = max - position;
+ }
+
+ position = easeOutExpo(decelerating, decelOrigin, decelDelta, kBounceTime);
+ return update(position, ++decelerating <= kBounceTime && Math.floor(position) > max);
+ }
+ } else if (position < min && constrained) {
+ if (velocity < 0) {
+ // Slowing down
+ var excess = min - position;
+ var elasticity = (1.0 - excess / bounceLimit);
+ velocity = Math.min(velocity + kBounceDecelRate * deltaTime, 0) * elasticity;
+ decelerating = 0;
+ } else {
+ // Bouncing back
+ if (!decelerating) {
+ decelOrigin = position;
+ decelDelta = min - position;
+ }
+ position = easeOutExpo(decelerating, decelOrigin, decelDelta, kBounceTime);
+ return update(position, ++decelerating <= kBounceTime && Math.ceil(position) < min);
+ }
+ } else {
+ // Slowing down
+ if (!decelerating) {
+ if (velocity < 0 && velocity < -kMaxVelocity) {
+ velocity = -kMaxVelocity;
+ } else if (velocity > 0 && velocity > kMaxVelocity) {
+ velocity = kMaxVelocity;
+ }
+ decelOrigin = velocity;
+ }
+
+ velocity = easeOutExpo(decelerating, decelOrigin, -decelOrigin, kDecelRate);
+
+ if (++decelerating > kDecelRate || Math.floor(velocity) == 0) {
+ continues = false;
+ }
+ }
+ }
+
+ position += velocity * deltaTime;
+ return update(position, continues);
+ }
+
+ function update(pos, continues) {
+ position = pos;
+ target.node[target.key] = position;
+ target.update(target.node, position);
+
+ var range = -min - max;
+ if (scrollbar && viewport < range) {
+ var viewable = viewport - kScrollbarMargin*2;
+ var height = (viewable/range) * viewable;
+ var scrollPosition = 0;
+ if (position > max) {
+ height = Math.max(height - (position-max), 5);
+ scrollPosition = 0;
+ } else if (position < min) {
+ height = Math.max(height - (min - position), 5);
+ scrollPosition = (viewable-height);
+ } else {
+ scrollPosition = Math.round((Math.abs(position) / range) * (viewable-height));
+ }
+ scrollPosition += kScrollbarMargin;
+ scrollbar.style.height = Math.round(height) + 'px';
+
+ moveElement(scrollbar, 0, scrollPosition);
+
+ if (touchMoved) {
+ scrollbar.style.opacity = '0.8';
+ scrollbar.style.webkitTransition = 'none';
+ }
+ }
+ return continues;
+ }
+
+ function terminator() {
+ if (paginated) {
+ update(Math.round(position/viewport) * viewport);
+ } else if (position > max && constrained) {
+ update(max);
+ } else if (position < min && constrained) {
+ update(min);
+ }
+ if (scrollbar) {
+ scrollbar.style.opacity = '0';
+ scrollbar.style.webkitTransition = 'opacity 0.2s linear';
+ }
+ }
+
+ return {
+ filter: target.filter,
+ disable: target.disable,
+ animator: animator,
+ terminator: terminator
+ };
+}
+
+function touchAnimation() {
+ var time = new Date().getTime();
+
+ for (var i = 0; i < touchTargets.length; ++i) {
+ var target = touchTargets[i];
+ var touch = target.filter(touchX, touchY);
+ if (!target.animator(touch, time)) {
+ target.terminator();
+ touchTargets.splice(i--, 1);
+ }
+ }
+
+ if (!touchTargets.length) {
+ stopAnimation();
+ }
+}
+
+// *************************************************************************************************
+
+function getTouchTargets(node) {
+ var targets = [];
+ while (node) {
+ if (node.nodeType == 1) {
+ var classes = node.className.split(' ');
+ if (classes.indexOf('scrollable') != -1) {
+ var paginated = classes.indexOf('paginated') != -1;
+ for (var i = 0; i < classes.length; ++i) {
+ var name = classes[i];
+ if (scrollers[name]) {
+ var target = scrollers[name](node);
+ target.key = 'scrollable_'+name;
+ target.paginated = paginated;
+ if (!(target.key in node)) {
+ node[target.key] = target.initial ? target.initial(node) : 0;
+ }
+
+ targets.push(target);
+ }
+ }
+ if (classes.indexOf('exclusive') != -1) {
+ break;
+ }
+ }
+ }
+ node = node.parentNode;
+ }
+ return targets;
+}
+
+function setTouched(target) {
+ var touched = [];
+ for (var n = target; n; n = n.parentNode) {
+ if (n.nodeType == 1) {
+ n.className = (n.className ? n.className + ' ' : '') + 'touched';
+ touched.push(n);
+ }
+ }
+ return touched;
+}
+
+function releaseTouched(touched) {
+ for (var i = 0; i < touched.length; ++i) {
+ var n = touched[i];
+ n.className = n.className.replace('touched', '');
+ }
+}
+
+function stopAnimation() {
+ if (animationInterval) {
+ clearInterval(animationInterval);
+ animationInterval = 0;
+
+ for (var i = 0; i < touchTargets.length; ++i) {
+ var target = touchTargets[i];
+ target.terminator();
+ }
+ touchTargets = [];
+ }
+}
+
+function moveElement(element, x, y) {
+ element.style.webkitTransform = 'translate3d('
+ +(x ? (Math.round(x)+'px') : '0')+','
+ +(y ? (Math.round(y)+'px') : '0')+','
+ +'0)';
+}
+
+function initScrollbar(element) {
+ if (!element.scrollableScrollbar) {
+ var scrollbar = element.scrollableScrollbar = document.createElement('div');
+ scrollbar.className = 'scrollableScrollbar';
+ scrollbar.style.cssText = [
+ 'position: absolute',
+ 'top: 0',
+ 'right: 2px',
+ 'width: 5px',
+ 'min-height: 6px',
+ 'background: #666',
+ 'opacity: 0',
+ '-webkit-border-radius: 2px 3px',
+ '-webkit-transform: translate3d(0,0,0)',
+ '-webkit-transition: opacity 0.15s linear'
+ ].join(';');
+ }
+ return element.scrollableScrollbar;
+}
+
+function easeOutExpo(t, b, c, d) {
+ return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+}
+
+// *************************************************************************************************
+
+function createXTarget(element) {
+ var parent = element.parentNode;
+ return {
+ node: element,
+ min: -parent.scrollWidth + parent.offsetWidth,
+ max: 0,
+ viewport: parent.offsetWidth,
+ bounce: parent.offsetWidth * kBounceLimit,
+ constrained: true,
+
+ filter: function(x, y) {
+ return x;
+ },
+
+ disable: function (x, y, startX, startY) {
+ var dx = Math.abs(x - startX);
+ var dy = Math.abs(y - startY);
+ if (dy > dx && dy > kLockThreshold) {
+ return true;
+ }
+ },
+
+ update: function(element, position) {
+ moveElement(element, position, element.scrollable_vertical);
+ }
+ };
+}
+
+function createYTarget(element) {
+ var parent = element.parentNode;
+ return {
+ node: element,
+ scrollbar: initScrollbar(element),
+ min: -parent.scrollHeight + parent.offsetHeight,
+ max: 0,
+ viewport: parent.offsetHeight,
+ bounce: parent.offsetHeight * kBounceLimit,
+ constrained: true,
+
+ filter: function(x, y) {
+ return y;
+ },
+
+ disable: function(x, y, startX, startY) {
+ var dx = Math.abs(x - startX);
+ var dy = Math.abs(y - startY);
+ if (dx > dy && dx > kLockThreshold) {
+ return true;
+ }
+ },
+
+ update: function(element, position) {
+ moveElement(element, element.scrollable_horizontal, position);
+ }
+ };
+}
+
+document.addEventListener('touchstart', onTouchStart, false);
+
+})();
Please sign in to comment.
Something went wrong with that request. Please try again.