public
Created — forked from davegurnell/ios-scroll.js

iOS HTML5 Scrollpane

  • Download Gist
ios-scroll.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
/* iOS scrollpane jQuery plugin, v1.0
* ==================================
*
* (c) 2011 Dave Gurnell
* http://boxandarrow.com
*
* Distributed under the Creative Commons Attribution 3.0 Unported licence:
* http://creativecommons.org/licenses/by/3.0/
*/
 
 
/* Initialise a scrollpane. Use this on HTML like:
*
* <div id="viewport">
* <div>First page</div>
* <div>Second page</div>
* <div>Third page</div>
* </div>
*
* $("#viewport").scrollPane();
*
* The method wil automatically position and resize the pages
* so they're the same size as the viewport. Touching and dragging
* on the pages will flip between them in the style of the iOS home
* screen. Options:
*
* - direction: "horizontal" or "vertical", default "horizontal"
*
* The scroll direction.
*
* - deadzone: int, default 25
*
* Distance the user has to drag before a page transition is
* triggered. Avoids accidental page transitions caused by
* brushing against the screen.
*
* - draggable: boolean, default true
*
* Setting this to false disables the touch gestures. This is
* useful if you only want to transition using the $().showpage()
* method (see bottom of the file).
*
* - setupCss: boolean, default true
*
* Whether to edit the CSS rules for the viewport and pages.
* Set this to false to do your own layout, but bear in mind the
* plugin only works if the pages are the same size as the viewport.
*
* Note that this option does not affect whether the method sets
* -webkit-transition and -webkit-transform on the viewport.
*
* - onscroll: (int int int -> void), default empty function
*
* Callback function that gets invoked whenever the page scrolls.
* Use this to hook up animations and status indicators elsewhere
* on the page.
*
* Arguments to the function are:
*
* - pos : int
*
* the (typically negative) position that we're scrolling to, in pixels
*
* - page : real
*
* the (typically positive, possibly fractional) position that we're
* scrolling to, in units of a page
*
* - duration : int
*
* the number of milliseconds we're going to take to get there
*
* - onscrollfinish: (int int -> void), default empty function
*
* Callback function that gets invoked when the viewport settles on a
* new page. pos and page arguments are the same as for onscroll.
*
*/
$.fn.scrollpane = function(options) {
options = $.extend({
direction: "horizontal",
deadzone: 15,
draggable: true,
setupCss: true,
onscroll: function(pos, page, duration) {
$('#debug').empty().prepend(pos);
},
onscrollfinish: function(pos, page) { }
}, options);
 
return this.each(function () {
// the scroll pane viewport
// jQuery
var outerElem = $(this);
// a large div containing the scrolling content
// jQuery
///DEBUG! heigt noch rausnehmen
var innerElem = $("<div style=\"height:100%;position: relative\"></div>");
innerElem.append(outerElem.children().remove());
outerElem.append(innerElem);
// cache these for later
// natural
var outerWidth = outerElem.width();
var outerHeight = outerElem.height();
// boolean
var horizontal = (options.direction == "horizontal");
// the number of pixels the user has to drag and release to trigger a page transition
// natural
var deadzone = Math.max(0, options.deadzone);
// the index of the current page. changed after the user completes each scrolling gesture.
// integer
var currentPage = 0;
// width of a page
// integer
// Alte Version
// var scrollUnit = horizontal ? outerWidth : outerHeight;
scrollUnit = 100
 
// x coordinate on the transform. -ve numbers go to the right,
// so this goes -ve as currentPage goes +ve
// integer (pixels)
var currentPos = 0;
 
// min and max scroll position:
// integer (pixels)
var scrollMax = 0;
var scrollMin = -scrollUnit * (innerElem.children().length - 1);
// time to settle after touched:
// natural (ms)
var settleTime = 500;
 
// dragMid and dragEnd are updated each frame of dragging:
// integer (pixels)
var dragStart = 0; // touch position when dragging starts
var dragMid = 0; // touch position on the last touchmove event
var dragEnd = 0; // touch position on this touchmove event
// +1 if dragging in +ve x direction, -1 if dragging in -ve x direction
// U(-1, +1)
var dragDir = 0;
 
// Check if the Device is Android
var isAndroid = (/android/gi).test(navigator.appVersion);
if(options.setupCss) {
outerElem.css({ "position": "relative", "overflow": "hidden" });
// position the pages:
innerElem.children().each(function(index) {
$(this).css({ "position" : "absolute",
"display" : "block",
"width" : "100%",
"height" : "100%" })
.css(horizontal ? "left" : "top", scrollUnit * index + "%");
});
}
// natural natural boolean -> void
function scrollTo(position, duration, finish) {
options.onscroll(position, -position/scrollUnit, duration);
if (!isAndroid) {
innerElem.css({
"-webkit-transition": "all " + (duration == 0 ? "0" : duration + "ms"),
"-webkit-transform": horizontal ?
("translate3d(" + position + "%, 0, 0)") :
("translate3d(0, " + position + "%, 0)") });
} else {
innerElem.css({
"left": horizontal ?
("" + position + "%") :
("translate3d(0, " + position + "%, 0)") });
}
 
if(finish) {
window.setTimeout(function() {
options.onscrollfinish(position, -position/scrollUnit, duration);
});
}
}
// Immediately set the 3D transform on the scroll pane.
// This causes Safari to create OpenGL resources to manage the animation.
// This sometimes causes a brief flicker, so best to do it at page load
// rather than waiting until the user starts to drag.
scrollTo(0, 0, true);
 
// set up the menu callback:
outerElem.data("showpage", function(page) {
// int
page = page < 0
? innerElem.children().length + page
: page;
currentPos = Math.max(scrollMin, Math.min(scrollMax, -page * scrollUnit));
currentPage = -currentPos / scrollUnit;
scrollTo(currentPos, settleTime, true);
});
// bind the touch drag events:
if(options.draggable) {
outerElem.bind("touchstart", function(wrap) {
var evt = wrap.originalEvent;
if(evt.touches.length == 1) {
dragStart = dragEnd = dragMid = horizontal ? evt.touches[0].pageX * 100 / outerElem.width() : evt.touches[0].pageY * 100 / outerElem.height();
}
// bind the touch drag event:
}).bind("touchmove", function(wrap) {
var evt = wrap.originalEvent;
if(evt.touches.length == 1) {
dragEnd = horizontal ? evt.touches[0].pageX * 100 / outerElem.width() : evt.touches[0].pageY * 100 / outerElem.height();
dragDir = (dragEnd - dragMid) > 0 ? 1 : -1;
currentPos += dragEnd - dragMid;
dragMid = dragEnd;
scrollTo(currentPos, 0, false);
}
// bind the touch end event:
}).bind("touchend", function(wrap) {
var evt = wrap.originalEvent;
// boolean
var reset = Math.abs(dragEnd - dragStart) < deadzone;
// real
var scrollPage = -1.0 * currentPos / scrollUnit;
// natural
var nextPage = reset
? currentPage
: (dragDir < 0
? Math.ceil(scrollPage)
: Math.floor(scrollPage));
 
// int
var nextPos = Math.max(scrollMin,
Math.min(scrollMax,
-scrollUnit * nextPage));
currentPos = nextPos;
currentPage = nextPage;
 
scrollTo(nextPos, settleTime, true);
});
}
});
};
 
// Once you've initialized a scrollpane with $().scrollpane(),
// you can use this method to cause it to programmatically scroll
// to a particular page. Useful for creating a navigation menu, or
// those little dots on Apple-store-style product galleries.
//
// Pages are indexed from 0 upwards. Negative numbers can be used
// to index pages from the right.
//
// int -> jQuery
$.fn.showpage = function(index) {
var fn = this.data("showpage");
fn(index);
return this;
};

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.