// see https://bugs.chromium.org/p/chromium/issues/detail?id=294514 for an explanation of the problem, with a very helpful automatic archival // If you use this "code" you're going to burn in a very special level of hell. // A level they reserve for child molesters and people who talk at the theater. function engageManualScrolling(element) { var start = 0; var handleStart = function(event) { start = element.scrollTop + event.touches[0].pageY; }; var handleMove = function(event) { element.scrollTop = start - event.touches[0].pageY; // abort default handler, otherwise we'd only scroll one line event.preventDefault(); }; var handleAbort = function() { element.removeEventListener('touchstart', handleStart, false); element.removeEventListener('touchmove', handleMove, false); element.removeEventListener('touchcancel', handleAbort, false); element.removeEventListener('touchend', handleAbort, false); }; element.addEventListener('touchstart', handleStart, false); element.addEventListener('touchmove', handleMove, false); element.addEventListener('touchcancel', handleAbort, false); element.addEventListener('touchend', handleAbort, false); } function hasCssOverflowScroll(element) { var style = window.getComputedStyle(element, null); return [ style.getPropertyValue('overflow'), style.getPropertyValue('overflow-x'), style.getPropertyValue('overflow-y'), ].some(function(overflow) { return overflow === 'auto' || overflow === 'scroll'; }); } function getScrollableElement(origin) { var element = origin; while (element) { if (hasCssOverflowScroll(element)) { return element; } // IE does know support parentElement on SVGElement element = element.parentNode; if (element && element.nodeType !== Node.ELEMENT_NODE) { element = null; } } return null; } document.documentElement.addEventListener('touchstart', function(event) { var scrollable = getScrollableElement(event.target); if (!scrollable) { return; } engageManualScrolling(scrollable); }, true);