inobounce.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*! iNoBounce - v0.1.0
  2. * https://github.com/lazd/iNoBounce/
  3. * Copyright (c) 2013 Larry Davis <lazdnet@gmail.com>; Licensed BSD */
  4. (function(global) {
  5. // Stores the Y position where the touch started
  6. var startY = 0;
  7. // Store enabled status
  8. var enabled = false;
  9. var handleTouchmove = function(evt) {
  10. // Get the element that was scrolled upon
  11. var el = evt.target;
  12. // Check all parent elements for scrollability
  13. while (el !== document.body) {
  14. // Get some style properties
  15. var style = window.getComputedStyle(el);
  16. if (!style) {
  17. // If we've encountered an element we can't compute the style for, get out
  18. break;
  19. }
  20. // Ignore range input element
  21. if (el.nodeName === 'INPUT' && el.getAttribute('type') === 'range') {
  22. return;
  23. }
  24. var scrolling = style.getPropertyValue('-webkit-overflow-scrolling');
  25. var overflowY = style.getPropertyValue('overflow-y');
  26. var height = parseInt(style.getPropertyValue('height'), 10);
  27. // Determine if the element should scroll
  28. var isScrollable = scrolling === 'touch' && (overflowY === 'auto' || overflowY === 'scroll');
  29. var canScroll = el.scrollHeight > el.offsetHeight;
  30. if (isScrollable && canScroll) {
  31. // Get the current Y position of the touch
  32. var curY = evt.touches ? evt.touches[0].screenY : evt.screenY;
  33. // Determine if the user is trying to scroll past the top or bottom
  34. // In this case, the window will bounce, so we have to prevent scrolling completely
  35. var isAtTop = (startY <= curY && el.scrollTop === 0);
  36. var isAtBottom = (startY >= curY && el.scrollHeight - el.scrollTop === height);
  37. // Stop a bounce bug when at the bottom or top of the scrollable element
  38. if (isAtTop || isAtBottom) {
  39. evt.preventDefault();
  40. }
  41. // No need to continue up the DOM, we've done our job
  42. return;
  43. }
  44. // Test the next parent
  45. el = el.parentNode;
  46. }
  47. // Stop the bouncing -- no parents are scrollable
  48. evt.preventDefault();
  49. };
  50. var handleTouchstart = function(evt) {
  51. // Store the first Y position of the touch
  52. startY = evt.touches ? evt.touches[0].screenY : evt.screenY;
  53. };
  54. var enable = function() {
  55. // Listen to a couple key touch events
  56. window.addEventListener('touchstart', handleTouchstart, false);
  57. window.addEventListener('touchmove', handleTouchmove, false);
  58. enabled = true;
  59. };
  60. var disable = function() {
  61. // Stop listening
  62. window.removeEventListener('touchstart', handleTouchstart, false);
  63. window.removeEventListener('touchmove', handleTouchmove, false);
  64. enabled = false;
  65. };
  66. var isEnabled = function() {
  67. return enabled;
  68. };
  69. // Enable by default if the browser supports -webkit-overflow-scrolling
  70. // Test this by setting the property with JavaScript on an element that exists in the DOM
  71. // Then, see if the property is reflected in the computed style
  72. var testDiv = document.createElement('div');
  73. document.documentElement.appendChild(testDiv);
  74. testDiv.style.WebkitOverflowScrolling = 'touch';
  75. var scrollSupport = 'getComputedStyle' in window && window.getComputedStyle(testDiv)['-webkit-overflow-scrolling'] === 'touch';
  76. document.documentElement.removeChild(testDiv);
  77. if (scrollSupport) {
  78. enable();
  79. }
  80. // A module to support enabling/disabling iNoBounce
  81. var iNoBounce = {
  82. enable: enable,
  83. disable: disable,
  84. isEnabled: isEnabled
  85. };
  86. if (typeof module !== 'undefined' && module.exports) {
  87. // Node.js Support
  88. module.exports = iNoBounce;
  89. }
  90. if (typeof global.define === 'function') {
  91. // AMD Support
  92. (function(define) {
  93. define('iNoBounce', [], function() { return iNoBounce; });
  94. }(global.define));
  95. }
  96. else {
  97. // Browser support
  98. global.iNoBounce = iNoBounce;
  99. }
  100. }(this));