diff --git a/SmoothScroll.js b/SmoothScroll.js index bd7ba2a..757ee17 100644 --- a/SmoothScroll.js +++ b/SmoothScroll.js @@ -101,16 +101,13 @@ function init() { } /** - * Please duplicate this radar for a Safari fix! - * rdar://22376037 - * https://openradar.appspot.com/radar?id=4965070979203072 - * - * Only applies to Safari now, Chrome fixed it in v45: + * Safari 10 fixed it, Chrome fixed it in v45: * This fixes a bug where the areas left and right to * the content does not trigger the onmousewheel event * on some pages. e.g.: html, body { height: 100% } */ - else if (scrollHeight > windowHeight && + else if (isOldSafari && + scrollHeight > windowHeight && (body.offsetHeight <= windowHeight || html.offsetHeight <= windowHeight)) { @@ -299,12 +296,10 @@ function wheel(event) { } var target = event.target; - var overflowing = overflowingAncestor(target); - // use default if there's no overflowing - // element or default action is prevented + // leave early if default action is prevented // or it's a zooming event with CTRL - if (!overflowing || event.defaultPrevented || event.ctrlKey) { + if (event.defaultPrevented || event.ctrlKey) { return true; } @@ -338,6 +333,20 @@ function wheel(event) { deltaX *= 40; deltaY *= 40; } + + var overflowing = overflowingAncestor(target); + + // nothing to do if there's no element that's scrollable + if (!overflowing) { + // except Chrome iframes seem to eat wheel events, which we need to + // propagate up, if the iframe has nothing overflowing to scroll + if (isFrame && isChrome) { + // change target to iframe element itself for the parent frame + Object.defineProperty(event, "target", {value: window.frameElement}); + return parent.wheel(event); + } + return true; + } // check if it's a touchpad scroll that should be ignored if (!options.touchpadSupport && isTouchpad(deltaY)) { @@ -404,10 +413,17 @@ function keydown(event) { } var shift, x = 0, y = 0; - var elem = overflowingAncestor(activeElement); - var clientHeight = elem.clientHeight; + var overflowing = overflowingAncestor(activeElement); + + if (!overflowing) { + // Chrome iframes seem to eat key events, which we need to + // propagate up, if the iframe has nothing overflowing to scroll + return (isFrame && isChrome) ? parent.keydown(event) : true; + } - if (elem == document.body) { + var clientHeight = overflowing.clientHeight; + + if (overflowing == document.body) { clientHeight = window.innerHeight; } @@ -429,11 +445,12 @@ function keydown(event) { y = clientHeight * 0.9; break; case key.home: - y = -elem.scrollTop; + y = -overflowing.scrollTop; break; case key.end: - var damt = elem.scrollHeight - elem.scrollTop - clientHeight; - y = (damt > 0) ? damt+10 : 0; + var scroll = overflowing.scrollHeight - overflowing.scrollTop; + var scrollRemaining = scroll - clientHeight; + y = (scrollRemaining > 0) ? scrollRemaining + 10 : 0; break; case key.left: x = -options.arrowScroll; @@ -445,7 +462,7 @@ function keydown(event) { return true; // a key we don't care about } - scrollArray(elem, x, y); + scrollArray(overflowing, x, y); event.preventDefault(); scheduleClearCache(); } @@ -562,7 +579,9 @@ function directionCheck(x, y) { var deltaBufferTimer; if (window.localStorage && localStorage.SS_deltaBuffer) { - deltaBuffer = localStorage.SS_deltaBuffer.split(','); + try { // #46 Safari throws in private browsing for localStorage + deltaBuffer = localStorage.SS_deltaBuffer.split(','); + } catch (e) { } } function isTouchpad(deltaY) { @@ -575,9 +594,9 @@ function isTouchpad(deltaY) { deltaBuffer.shift(); clearTimeout(deltaBufferTimer); deltaBufferTimer = setTimeout(function () { - if (window.localStorage) { + try { // #46 Safari throws in private browsing for localStorage localStorage.SS_deltaBuffer = deltaBuffer.join(','); - } + } catch (e) { } }, 1000); return !allDeltasDivisableBy(120) && !allDeltasDivisableBy(100); } @@ -688,6 +707,7 @@ var isChrome = /chrome/i.test(userAgent) && !isEdge; var isSafari = /safari/i.test(userAgent) && !isEdge; var isMobile = /mobile/i.test(userAgent); var isIEWin7 = /Windows NT 6.1/i.test(userAgent) && /rv:11/i.test(userAgent); +var isOldSafari = isSafari && (/Version\/8/i.test(userAgent) || /Version\/9/i.test(userAgent)); var isEnabledForBrowser = (isChrome || isSafari || isIEWin7) && !isMobile; var wheelEvent;