123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- /*! iNoBounce - v0.2.0
- * https://github.com/lazd/iNoBounce/
- * Copyright (c) 2013 Larry Davis <lazdnet@gmail.com>; Licensed BSD */
- (function(global) {
- // Stores the Y position where the touch started
- var startY = 0;
- // Store enabled status
- var enabled = false;
- var supportsPassiveOption = false;
- try {
- var opts = Object.defineProperty({}, 'passive', {
- get: function() {
- supportsPassiveOption = true;
- }
- });
- window.addEventListener('test', null, opts);
- } catch (e) {}
- var handleTouchmove = function(evt) {
- // Get the element that was scrolled upon
- var el = evt.target;
- // Allow zooming
- var zoom = window.innerWidth / window.document.documentElement.clientWidth;
- if (evt.touches.length > 1 || zoom !== 1) {
- return;
- }
- // Check all parent elements for scrollability
- while (el !== document.body && el !== document) {
- // Get some style properties
- var style = window.getComputedStyle(el);
- if (!style) {
- // If we've encountered an element we can't compute the style for, get out
- break;
- }
- // Ignore range input element
- if (el.nodeName === 'INPUT' && el.getAttribute('type') === 'range') {
- return;
- }
- var scrolling = style.getPropertyValue('-webkit-overflow-scrolling');
- var overflowY = style.getPropertyValue('overflow-y');
- var height = parseInt(style.getPropertyValue('height'), 10);
- // Determine if the element should scroll
- var isScrollable = scrolling === 'touch' && (overflowY === 'auto' || overflowY === 'scroll');
- var canScroll = el.scrollHeight > el.offsetHeight;
- if (isScrollable && canScroll) {
- // Get the current Y position of the touch
- var curY = evt.touches ? evt.touches[0].screenY : evt.screenY;
- // Determine if the user is trying to scroll past the top or bottom
- // In this case, the window will bounce, so we have to prevent scrolling completely
- var isAtTop = (startY <= curY && el.scrollTop === 0);
- var isAtBottom = (startY >= curY && el.scrollHeight - el.scrollTop === height);
- // Stop a bounce bug when at the bottom or top of the scrollable element
- if (isAtTop || isAtBottom) {
- evt.preventDefault();
- }
- // No need to continue up the DOM, we've done our job
- return;
- }
- // Test the next parent
- el = el.parentNode;
- }
- // Stop the bouncing -- no parents are scrollable
- evt.preventDefault();
- };
- var handleTouchstart = function(evt) {
- // Store the first Y position of the touch
- startY = evt.touches ? evt.touches[0].screenY : evt.screenY;
- };
- var enable = function() {
- // Listen to a couple key touch events
- window.addEventListener('touchstart', handleTouchstart, supportsPassiveOption ? { passive : false } : false);
- window.addEventListener('touchmove', handleTouchmove, supportsPassiveOption ? { passive : false } : false);
- enabled = true;
- };
- var disable = function() {
- // Stop listening
- window.removeEventListener('touchstart', handleTouchstart, false);
- window.removeEventListener('touchmove', handleTouchmove, false);
- enabled = false;
- };
- var isEnabled = function() {
- return enabled;
- };
- // Enable by default if the browser supports -webkit-overflow-scrolling
- // Test this by setting the property with JavaScript on an element that exists in the DOM
- // Then, see if the property is reflected in the computed style
- var testDiv = document.createElement('div');
- document.documentElement.appendChild(testDiv);
- testDiv.style.WebkitOverflowScrolling = 'touch';
- var scrollSupport = 'getComputedStyle' in window && window.getComputedStyle(testDiv)['-webkit-overflow-scrolling'] === 'touch';
- document.documentElement.removeChild(testDiv);
- if (scrollSupport) {
- enable();
- }
- // A module to support enabling/disabling iNoBounce
- var iNoBounce = {
- enable: enable,
- disable: disable,
- isEnabled: isEnabled
- };
- if (typeof module !== 'undefined' && module.exports) {
- // Node.js Support
- module.exports = iNoBounce;
- }
- if (typeof global.define === 'function') {
- // AMD Support
- (function(define) {
- define('iNoBounce', [], function() { return iNoBounce; });
- }(global.define));
- }
- else {
- // Browser support
- global.iNoBounce = iNoBounce;
- }
- }(this));
|