scroll-behavior-polyfill
Advanced tools
Comparing version 2.0.8 to 2.0.9
@@ -0,1 +1,7 @@ | ||
## [2.0.9](https://github.com/wessberg/scroll-behavior-polyfill/compare/v2.0.8...v2.0.9) (2019-07-18) | ||
### Bug Fixes | ||
- **bug:** fixes an issue when using this polyfill along with css-scroll-snap. Closes [#5](https://github.com/wessberg/scroll-behavior-polyfill/issues/5) ([c50582b](https://github.com/wessberg/scroll-behavior-polyfill/commit/c50582b)), closes [#7](https://github.com/wessberg/scroll-behavior-polyfill/issues/7) | ||
## [2.0.8](https://github.com/wessberg/scroll-behavior-polyfill/compare/v2.0.7...v2.0.8) (2019-06-21) | ||
@@ -2,0 +8,0 @@ |
(function () { | ||
'use strict'; | ||
var UNSUPPORTED_ENVIRONMENT = typeof window === "undefined"; | ||
/** | ||
@@ -8,3 +10,3 @@ * Is true if the browser natively supports the 'scroll-behavior' CSS-property. | ||
*/ | ||
var SUPPORTS_SCROLL_BEHAVIOR = "scrollBehavior" in document.documentElement.style; | ||
var SUPPORTS_SCROLL_BEHAVIOR = UNSUPPORTED_ENVIRONMENT ? false : "scrollBehavior" in document.documentElement.style; | ||
@@ -56,5 +58,59 @@ | ||
function getScrollingElement() { | ||
if (document.scrollingElement != null) { | ||
return document.scrollingElement; | ||
} | ||
else { | ||
return document.documentElement; | ||
} | ||
} | ||
var STYLE_ATTRIBUTE_PROPERTY_NAME = "scroll-behavior"; | ||
var STYLE_ATTRIBUTE_PROPERTY_REGEXP = new RegExp(STYLE_ATTRIBUTE_PROPERTY_NAME + ":\\s*([^;]*)"); | ||
/** | ||
* Given an Element, this function appends the given ScrollBehavior CSS property value to the elements' 'style' attribute. | ||
* If it doesnt already have one, it will add it. | ||
* @param {Element} element | ||
* @param {ScrollBehavior} behavior | ||
*/ | ||
function appendScrollBehaviorToStyleAttribute(element, behavior) { | ||
var addition = STYLE_ATTRIBUTE_PROPERTY_NAME + ":" + behavior; | ||
var attributeValue = element.getAttribute("style"); | ||
if (attributeValue == null || attributeValue === "") { | ||
element.setAttribute("style", addition); | ||
return; | ||
} | ||
// The style attribute may already include a 'scroll-behavior:<something>' in which case that should be replaced | ||
var existingValueForProperty = parseScrollBehaviorFromStyleAttribute(element); | ||
if (existingValueForProperty != null) { | ||
var replacementProperty = STYLE_ATTRIBUTE_PROPERTY_NAME + ":" + existingValueForProperty; | ||
// Replace the variant that ends with a semi-colon which it may | ||
attributeValue = attributeValue.replace(replacementProperty + ";", ""); | ||
// Replace the variant that *doesn't* end with a semi-colon | ||
attributeValue = attributeValue.replace(replacementProperty, ""); | ||
} | ||
// Now, append the behavior to the string. | ||
element.setAttribute("style", attributeValue.endsWith(";") ? "" + attributeValue + addition : ";" + attributeValue + addition); | ||
} | ||
/** | ||
* Given an Element, this function attempts to parse its 'style' attribute (if it has one)' to extract | ||
* a value for the 'scroll-behavior' CSS property (if it is given within that style attribute) | ||
* @param {Element} element | ||
* @returns {ScrollBehavior?} | ||
*/ | ||
function parseScrollBehaviorFromStyleAttribute(element) { | ||
var styleAttributeValue = element.getAttribute("style"); | ||
if (styleAttributeValue != null && styleAttributeValue.includes(STYLE_ATTRIBUTE_PROPERTY_NAME)) { | ||
var match = styleAttributeValue.match(STYLE_ATTRIBUTE_PROPERTY_REGEXP); | ||
if (match != null) { | ||
var _a = __read(match, 2), behavior = _a[1]; | ||
if (behavior != null && behavior !== "") { | ||
return behavior; | ||
} | ||
} | ||
} | ||
return undefined; | ||
} | ||
var styleDeclarationPropertyName = "scrollBehavior"; | ||
var styleAttributePropertyName = "scroll-behavior"; | ||
var styleAttributePropertyNameRegex = new RegExp(styleAttributePropertyName + ":\\s*([^;]*)"); | ||
/** | ||
@@ -71,3 +127,3 @@ * Determines the scroll behavior to use, depending on the given ScrollOptions and the position of the Element | ||
return "smooth"; | ||
var target = "style" in inputTarget ? inputTarget : document.scrollingElement != null ? document.scrollingElement : document.documentElement; | ||
var target = "style" in inputTarget ? inputTarget : getScrollingElement(); | ||
var value; | ||
@@ -90,12 +146,3 @@ if ("style" in target) { | ||
// Otherwise, check if it is set as an inline style | ||
var styleAttributeValue = target.getAttribute("style"); | ||
if (styleAttributeValue != null && styleAttributeValue.includes(styleAttributePropertyName)) { | ||
var match = styleAttributeValue.match(styleAttributePropertyNameRegex); | ||
if (match != null) { | ||
var _a = __read(match, 2), behavior = _a[1]; | ||
if (behavior != null && behavior !== "") { | ||
value = behavior; | ||
} | ||
} | ||
} | ||
value = parseScrollBehaviorFromStyleAttribute(target); | ||
} | ||
@@ -116,2 +163,4 @@ if (value == null) { | ||
var HALF = 0.5; | ||
@@ -127,2 +176,91 @@ /** | ||
var NOOP = { | ||
reset: function () { } | ||
}; | ||
var map = new WeakMap(); | ||
function disableScrollSnap(scroller) { | ||
// If scroll-behavior is natively supported, there's no need for this fix | ||
if (SUPPORTS_SCROLL_BEHAVIOR) { | ||
return NOOP; | ||
} | ||
var scrollingElement = getScrollingElement(); | ||
var cachedScrollSnapValue; | ||
var cachedScrollBehaviorStyleAttributeValue; | ||
var secondaryScroller; | ||
var secondaryScrollerCachedScrollSnapValue; | ||
var secondaryScrollerCachedScrollBehaviorStyleAttributeValue; | ||
var existingResult = map.get(scroller); | ||
if (existingResult != null) { | ||
cachedScrollSnapValue = existingResult.cachedScrollSnapValue; | ||
cachedScrollBehaviorStyleAttributeValue = existingResult.cachedScrollBehaviorStyleAttributeValue; | ||
secondaryScroller = existingResult.secondaryScroller; | ||
secondaryScrollerCachedScrollSnapValue = existingResult.secondaryScrollerCachedScrollSnapValue; | ||
secondaryScrollerCachedScrollBehaviorStyleAttributeValue = existingResult.secondaryScrollerCachedScrollBehaviorStyleAttributeValue; | ||
existingResult.release(); | ||
} | ||
else { | ||
cachedScrollSnapValue = scroller.style.scrollSnapType === "" ? null : scroller.style.scrollSnapType; | ||
cachedScrollBehaviorStyleAttributeValue = parseScrollBehaviorFromStyleAttribute(scroller); | ||
secondaryScroller = scroller === scrollingElement && scrollingElement !== document.body ? document.body : undefined; | ||
secondaryScrollerCachedScrollSnapValue = | ||
secondaryScroller == null ? undefined : secondaryScroller.style.scrollSnapType === "" ? null : secondaryScroller.style.scrollSnapType; | ||
secondaryScrollerCachedScrollBehaviorStyleAttributeValue = | ||
secondaryScroller == null ? undefined : parseScrollBehaviorFromStyleAttribute(secondaryScroller); | ||
var cachedComputedScrollSnapValue = getComputedStyle(scroller).getPropertyValue("scroll-snap-type"); | ||
var secondaryScrollerCachedComputedScrollSnapValue = secondaryScroller == null ? undefined : getComputedStyle(secondaryScroller).getPropertyValue("scroll-snap-type"); | ||
// If it just so happens that there actually isn't any scroll snapping going on, there's no point in performing any additional work here. | ||
if (cachedComputedScrollSnapValue === "none" && secondaryScrollerCachedComputedScrollSnapValue === "none") { | ||
return NOOP; | ||
} | ||
} | ||
scroller.style.scrollSnapType = "none"; | ||
if (secondaryScroller !== undefined) { | ||
secondaryScroller.style.scrollSnapType = "none"; | ||
} | ||
if (cachedScrollBehaviorStyleAttributeValue !== undefined) { | ||
appendScrollBehaviorToStyleAttribute(scroller, cachedScrollBehaviorStyleAttributeValue); | ||
} | ||
if (secondaryScroller !== undefined && secondaryScrollerCachedScrollBehaviorStyleAttributeValue !== undefined) { | ||
appendScrollBehaviorToStyleAttribute(secondaryScroller, secondaryScrollerCachedScrollBehaviorStyleAttributeValue); | ||
} | ||
var hasReleased = false; | ||
var eventTarget = scroller === scrollingElement ? window : scroller; | ||
function release() { | ||
eventTarget.removeEventListener("scroll", resetHandler); | ||
map["delete"](scroller); | ||
hasReleased = true; | ||
} | ||
function resetHandler() { | ||
scroller.style.scrollSnapType = cachedScrollSnapValue; | ||
if (secondaryScroller != null && secondaryScrollerCachedScrollSnapValue !== undefined) { | ||
secondaryScroller.style.scrollSnapType = secondaryScrollerCachedScrollSnapValue; | ||
} | ||
if (cachedScrollBehaviorStyleAttributeValue !== undefined) { | ||
appendScrollBehaviorToStyleAttribute(scroller, cachedScrollBehaviorStyleAttributeValue); | ||
} | ||
if (secondaryScroller !== undefined && secondaryScrollerCachedScrollBehaviorStyleAttributeValue !== undefined) { | ||
appendScrollBehaviorToStyleAttribute(secondaryScroller, secondaryScrollerCachedScrollBehaviorStyleAttributeValue); | ||
} | ||
release(); | ||
} | ||
function reset() { | ||
setTimeout(function () { | ||
if (hasReleased) | ||
return; | ||
eventTarget.addEventListener("scroll", resetHandler); | ||
}); | ||
} | ||
map.set(scroller, { | ||
release: release, | ||
cachedScrollSnapValue: cachedScrollSnapValue, | ||
cachedScrollBehaviorStyleAttributeValue: cachedScrollBehaviorStyleAttributeValue, | ||
secondaryScroller: secondaryScroller, | ||
secondaryScrollerCachedScrollSnapValue: secondaryScrollerCachedScrollSnapValue, | ||
secondaryScrollerCachedScrollBehaviorStyleAttributeValue: secondaryScrollerCachedScrollBehaviorStyleAttributeValue | ||
}); | ||
return { | ||
reset: reset | ||
}; | ||
} | ||
/** | ||
@@ -138,3 +276,3 @@ * The duration of a smooth scroll | ||
function smoothScroll(options) { | ||
var startTime = options.startTime, startX = options.startX, startY = options.startY, endX = options.endX, endY = options.endY, method = options.method; | ||
var startTime = options.startTime, startX = options.startX, startY = options.startY, endX = options.endX, endY = options.endY, method = options.method, scroller = options.scroller; | ||
var timeLapsed = 0; | ||
@@ -144,2 +282,4 @@ var distanceX = endX - startX; | ||
var speed = Math.max(Math.abs((distanceX / 1000) * SCROLL_TIME), Math.abs((distanceY / 1000) * SCROLL_TIME)); | ||
// Temporarily disables any scroll snapping that may be active since it fights for control over the scroller with this polyfill | ||
var scrollSnapFix = disableScrollSnap(scroller); | ||
requestAnimationFrame(function animate(timestamp) { | ||
@@ -154,2 +294,8 @@ timeLapsed += timestamp - startTime; | ||
} | ||
else { | ||
if (scrollSnapFix != null) { | ||
scrollSnapFix.reset(); | ||
scrollSnapFix = undefined; | ||
} | ||
} | ||
}); | ||
@@ -170,13 +316,13 @@ } | ||
var ELEMENT_ORIGINAL_SCROLL = Element.prototype.scroll; | ||
var ELEMENT_ORIGINAL_SCROLL = UNSUPPORTED_ENVIRONMENT ? undefined : Element.prototype.scroll; | ||
var WINDOW_ORIGINAL_SCROLL = window.scroll; | ||
var WINDOW_ORIGINAL_SCROLL = UNSUPPORTED_ENVIRONMENT ? undefined : window.scroll; | ||
var ELEMENT_ORIGINAL_SCROLL_BY = Element.prototype.scrollBy; | ||
var ELEMENT_ORIGINAL_SCROLL_BY = UNSUPPORTED_ENVIRONMENT ? undefined : Element.prototype.scrollBy; | ||
var WINDOW_ORIGINAL_SCROLL_BY = window.scrollBy; | ||
var WINDOW_ORIGINAL_SCROLL_BY = UNSUPPORTED_ENVIRONMENT ? undefined : window.scrollBy; | ||
var ELEMENT_ORIGINAL_SCROLL_TO = Element.prototype.scrollTo; | ||
var ELEMENT_ORIGINAL_SCROLL_TO = UNSUPPORTED_ENVIRONMENT ? undefined : Element.prototype.scrollTo; | ||
var WINDOW_ORIGINAL_SCROLL_TO = window.scrollTo; | ||
var WINDOW_ORIGINAL_SCROLL_TO = UNSUPPORTED_ENVIRONMENT ? undefined : window.scrollTo; | ||
@@ -281,3 +427,4 @@ /** | ||
endY: Math.floor(kind === "scrollBy" ? startY + y : y), | ||
method: getOriginalScrollMethodForKind("scrollTo", window).bind(window) | ||
method: getOriginalScrollMethodForKind("scrollTo", window).bind(window), | ||
scroller: getScrollingElement() | ||
}; | ||
@@ -295,3 +442,4 @@ } | ||
endY: Math.floor(kind === "scrollBy" ? startY + y : y), | ||
method: getOriginalScrollMethodForKind("scrollTo", element).bind(element) | ||
method: getOriginalScrollMethodForKind("scrollTo", element).bind(element), | ||
scroller: element | ||
}; | ||
@@ -463,3 +611,2 @@ } | ||
var scrollingElement = document.scrollingElement != null ? document.scrollingElement : document.documentElement; | ||
/** | ||
@@ -492,2 +639,3 @@ * Returns true if the given overflow property represents a scrollable overflow value | ||
var currentElement = target; | ||
var scrollingElement = getScrollingElement(); | ||
while (currentElement != null) { | ||
@@ -577,3 +725,3 @@ var behavior = getScrollBehavior(currentElement); | ||
var ELEMENT_ORIGINAL_SCROLL_INTO_VIEW = Element.prototype.scrollIntoView; | ||
var ELEMENT_ORIGINAL_SCROLL_INTO_VIEW = UNSUPPORTED_ENVIRONMENT ? undefined : Element.prototype.scrollIntoView; | ||
@@ -708,3 +856,3 @@ /** | ||
// Used to handle the top most element that can be scrolled | ||
var scrollingElement = document.scrollingElement || document.documentElement; | ||
var scrollingElement = getScrollingElement(); | ||
// Support pinch-zooming properly, making sure elements scroll into the visual viewport | ||
@@ -843,3 +991,5 @@ // Browsers that don't support visualViewport will report the layout viewport dimensions on document.documentElement.clientWidth/Height | ||
var ELEMENT_ORIGINAL_SCROLL_TOP_SET_DESCRIPTOR = Object.getOwnPropertyDescriptor(Element.prototype, "scrollTop").set; | ||
var ELEMENT_ORIGINAL_SCROLL_TOP_SET_DESCRIPTOR = UNSUPPORTED_ENVIRONMENT | ||
? undefined | ||
: Object.getOwnPropertyDescriptor(Element.prototype, "scrollTop").set; | ||
@@ -861,3 +1011,5 @@ /** | ||
var ELEMENT_ORIGINAL_SCROLL_LEFT_SET_DESCRIPTOR = Object.getOwnPropertyDescriptor(Element.prototype, "scrollLeft").set; | ||
var ELEMENT_ORIGINAL_SCROLL_LEFT_SET_DESCRIPTOR = UNSUPPORTED_ENVIRONMENT | ||
? undefined | ||
: Object.getOwnPropertyDescriptor(Element.prototype, "scrollLeft").set; | ||
@@ -903,5 +1055,7 @@ /** | ||
*/ | ||
var SUPPORTS_ELEMENT_PROTOTYPE_SCROLL_METHODS = "scroll" in Element.prototype && "scrollTo" in Element.prototype && "scrollBy" in Element.prototype && "scrollIntoView" in Element.prototype; | ||
var SUPPORTS_ELEMENT_PROTOTYPE_SCROLL_METHODS = UNSUPPORTED_ENVIRONMENT | ||
? false | ||
: "scroll" in Element.prototype && "scrollTo" in Element.prototype && "scrollBy" in Element.prototype && "scrollIntoView" in Element.prototype; | ||
if (!SUPPORTS_SCROLL_BEHAVIOR || !SUPPORTS_ELEMENT_PROTOTYPE_SCROLL_METHODS) { | ||
if (!UNSUPPORTED_ENVIRONMENT && (!SUPPORTS_SCROLL_BEHAVIOR || !SUPPORTS_ELEMENT_PROTOTYPE_SCROLL_METHODS)) { | ||
patch(); | ||
@@ -908,0 +1062,0 @@ } |
{ | ||
"name": "scroll-behavior-polyfill", | ||
"version": "2.0.8", | ||
"version": "2.0.9", | ||
"description": "A polyfill for the 'scroll-behavior' CSS-property", | ||
@@ -54,14 +54,14 @@ "repository": { | ||
"devDependencies": { | ||
"@wessberg/rollup-plugin-ts": "1.1.59", | ||
"@wessberg/scaffold": "1.0.18", | ||
"@wessberg/rollup-plugin-ts": "1.1.62", | ||
"@wessberg/scaffold": "1.0.19", | ||
"@wessberg/ts-config": "^0.0.41", | ||
"rollup": "^1.16.1", | ||
"rollup-plugin-node-resolve": "^5.0.3", | ||
"rollup": "^1.17.0", | ||
"rollup-plugin-node-resolve": "^5.2.0", | ||
"tslib": "^1.10.0", | ||
"tslint": "^5.18.0", | ||
"typescript": "^3.5.2", | ||
"typescript": "^3.5.3", | ||
"standard-changelog": "^2.0.11", | ||
"prettier": "^1.18.2", | ||
"pretty-quick": "^1.11.1", | ||
"husky": "^2.4.1", | ||
"husky": "^3.0.0", | ||
"np": "^5.0.3" | ||
@@ -68,0 +68,0 @@ }, |
@@ -185,2 +185,3 @@ <!-- SHADOW_SECTION_LOGO_START --> | ||
- `Object.defineProperty` | ||
- `WeakMap` | ||
@@ -187,0 +188,0 @@ For by far the most browsers, these features will already be natively available. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
149222
992
237