@polymer/iron-fit-behavior
Advanced tools
Comparing version 3.0.2 to 3.1.0
@@ -143,2 +143,9 @@ /** | ||
autoFitOnAttach: boolean|null|undefined; | ||
/** | ||
* If true and scrollbars are added to `sizingTarget` after it is | ||
* positioned, the size of the added scrollbars will be added to its | ||
* `maxWidth` and `maxHeight`. | ||
*/ | ||
expandSizingTargetForScrollbars: boolean|null|undefined; | ||
_fitInfo: object|null; | ||
@@ -145,0 +152,0 @@ readonly _fitWidth: any; |
@@ -15,2 +15,41 @@ /** | ||
// IE11 has a bug where an element with (1) `overflow: auto;`, (2) size based on | ||
// its content's natural size, (3) absolute positioning (either `absolute` or | ||
// `fixed`), and (4) use `max-width` to constrain its width will place its | ||
// vertical scrollbar outside the area constrained by `max-width`. | ||
// | ||
// Unlike other browsers, IE11 doesn't support changing the size of scrollbars | ||
// with CSS, so we don't need to read this value live from the element in | ||
// question when trying to work around the bug. | ||
let verticalScrollbarMaxWidthBugOffset = undefined; | ||
const getVerticalScrollbarMaxWidthBugOffset = () => { | ||
if (verticalScrollbarMaxWidthBugOffset !== undefined) { | ||
return verticalScrollbarMaxWidthBugOffset; | ||
} | ||
const container = document.createElement('div'); | ||
Object.assign(container.style, { | ||
overflow: 'auto', | ||
position: 'fixed', | ||
left: '0px', | ||
top: '0px', | ||
maxWidth: '100px', | ||
maxHeight: '100px', | ||
}); | ||
const content = document.createElement('div'); | ||
content.style.width = '200px'; | ||
content.style.height = '200px'; | ||
container.appendChild(content); | ||
document.body.appendChild(container); | ||
verticalScrollbarMaxWidthBugOffset = | ||
Math.abs(container.offsetWidth - 100) > 1 ? | ||
container.offsetWidth - container.clientWidth : | ||
0; | ||
document.body.removeChild(container); | ||
return verticalScrollbarMaxWidthBugOffset; | ||
}; | ||
/** | ||
@@ -157,2 +196,9 @@ `Polymer.IronFitBehavior` fits an element in another element using `max-height` | ||
/** | ||
* If true and scrollbars are added to `sizingTarget` after it is | ||
* positioned, the size of the added scrollbars will be added to its | ||
* `maxWidth` and `maxHeight`. | ||
*/ | ||
expandSizingTargetForScrollbars: {type: Boolean, value: false}, | ||
/** @type {?Object} */ | ||
@@ -374,2 +420,4 @@ _fitInfo: {type: Object} | ||
window.ShadyDOM && window.ShadyDOM.flush(); | ||
this.style.position = 'fixed'; | ||
@@ -387,2 +435,13 @@ // Need border-box for margin/padding. | ||
let unpositionedOffsetWidth; | ||
let unpositionedOffsetHeight; | ||
let unpositionedClientWidth; | ||
let unpositionedClientHeight; | ||
if (this.expandSizingTargetForScrollbars) { | ||
unpositionedOffsetWidth = this.sizingTarget.offsetWidth; | ||
unpositionedOffsetHeight = this.sizingTarget.offsetHeight; | ||
unpositionedClientWidth = this.sizingTarget.clientWidth; | ||
unpositionedClientHeight = this.sizingTarget.clientHeight; | ||
} | ||
var margin = this._fitInfo.margin; | ||
@@ -422,10 +481,102 @@ | ||
// minWidth/minHeight. | ||
this.sizingTarget.style.maxWidth = | ||
Math.max(right - left, this._fitInfo.sizedBy.minWidth) + 'px'; | ||
this.sizingTarget.style.maxHeight = | ||
Math.max(bottom - top, this._fitInfo.sizedBy.minHeight) + 'px'; | ||
const maxWidth = Math.max(right - left, this._fitInfo.sizedBy.minWidth); | ||
const maxHeight = Math.max(bottom - top, this._fitInfo.sizedBy.minHeight); | ||
this.sizingTarget.style.maxWidth = maxWidth + 'px'; | ||
this.sizingTarget.style.maxHeight = maxHeight + 'px'; | ||
// Remove the offset caused by any stacking context. | ||
this.style.left = (left - rect.left) + 'px'; | ||
this.style.top = (top - rect.top) + 'px'; | ||
const leftPosition = left - rect.left; | ||
const topPosition = top - rect.top; | ||
this.style.left = `${leftPosition}px`; | ||
this.style.top = `${topPosition}px`; | ||
if (this.expandSizingTargetForScrollbars) { | ||
// Expand the height first - i.e. in the typical block direction - in case | ||
// this expands the element enough to remove the vertical scrollbar. | ||
const positionedOffsetHeight = this.sizingTarget.offsetHeight; | ||
const positionedClientHeight = this.sizingTarget.clientHeight; | ||
const unpositionedHeightDelta = | ||
unpositionedOffsetHeight - unpositionedClientHeight; | ||
const positionedHeightDelta = | ||
positionedOffsetHeight - positionedClientHeight; | ||
const sizingTargetScrollbarHeight = | ||
positionedHeightDelta - unpositionedHeightDelta; | ||
if (sizingTargetScrollbarHeight > 0) { | ||
// Expand `maxHeight` by `sizingTargetScrollbarHeight` up to the overall | ||
// allowed height within `fitRect`. | ||
const fitRectMaxHeight = fitRect.height - margin.top - margin.bottom; | ||
const newMaxHeight = | ||
Math.min(fitRectMaxHeight, maxHeight + sizingTargetScrollbarHeight); | ||
this.sizingTarget.style.maxHeight = `${newMaxHeight}px`; | ||
// Measure the element's real change in height. This may not equal | ||
// `sizingTargetScrollbarHeight` if the overflow amount is less than the | ||
// scrollbar size. | ||
const offsetHeight = this.sizingTarget.offsetHeight; | ||
const addedHeight = offsetHeight - positionedOffsetHeight; | ||
// Adjust the top position if the alignment requires it. | ||
let newTopPosition; | ||
if (position.verticalAlign === 'top') { | ||
newTopPosition = topPosition; | ||
} else if (position.verticalAlign === 'middle') { | ||
newTopPosition = topPosition - addedHeight / 2; | ||
} else if (position.verticalAlign === 'bottom') { | ||
newTopPosition = topPosition - addedHeight; | ||
} | ||
// Constrain the new top position based on `fitRect` again. | ||
newTopPosition = Math.max( | ||
fitRect.top + margin.top, | ||
Math.min( | ||
newTopPosition, fitRect.bottom - margin.bottom - offsetHeight)); | ||
this.style.top = `${newTopPosition}px`; | ||
} | ||
const positionedOffsetWidth = this.sizingTarget.offsetWidth; | ||
const positionedClientWidth = this.sizingTarget.clientWidth; | ||
const unpositionedWidthDelta = | ||
unpositionedOffsetWidth - unpositionedClientWidth; | ||
const positionedWidthDelta = | ||
positionedOffsetWidth - positionedClientWidth; | ||
const sizingTargetScrollbarWidth = | ||
positionedWidthDelta - unpositionedWidthDelta; | ||
if (sizingTargetScrollbarWidth > 0) { | ||
const maxWidthBugOffset = getVerticalScrollbarMaxWidthBugOffset(); | ||
// Expand `maxWidth` by `sizingTargetScrollbarWidth` up to the overall | ||
// allowed width within `fitRect`. | ||
const fitRectMaxWidth = fitRect.width - margin.left - margin.right; | ||
const newMaxWidth = Math.min( | ||
fitRectMaxWidth, | ||
maxWidth + sizingTargetScrollbarWidth - maxWidthBugOffset); | ||
this.sizingTarget.style.maxWidth = `${newMaxWidth}px`; | ||
// Measure the element's real change in width. This may not equal | ||
// `sizingTargetScrollbarWidth` if the overflow amount is less than the | ||
// scrollbar size. | ||
const offsetWidth = this.sizingTarget.offsetWidth + maxWidthBugOffset; | ||
const addedWidth = offsetWidth - positionedOffsetWidth; | ||
// Adjust the left position if the alignment requires it. | ||
let newLeftPosition; | ||
if (position.horizontalAlign === 'left') { | ||
newLeftPosition = leftPosition; | ||
} else if (position.horizontalAlign === 'center') { | ||
newLeftPosition = leftPosition - addedWidth / 2; | ||
} else if (position.horizontalAlign === 'right') { | ||
newLeftPosition = leftPosition - addedWidth; | ||
} | ||
// Constrain the new left position based on `fitRect` again. | ||
newLeftPosition = Math.max( | ||
fitRect.left + margin.left, | ||
Math.min( | ||
newLeftPosition, fitRect.right - margin.right - offsetWidth)); | ||
this.style.left = `${newLeftPosition}px`; | ||
} | ||
} | ||
}, | ||
@@ -432,0 +583,0 @@ |
@@ -15,2 +15,3 @@ { | ||
"devDependencies": { | ||
"@polymer/gen-typescript-declarations": "^1.5.1", | ||
"@polymer/iron-demo-helpers": "^3.0.1", | ||
@@ -20,4 +21,3 @@ "@polymer/paper-styles": "^3.0.0-pre.26", | ||
"wct-browser-legacy": "^1.0.1", | ||
"webmat": "^0.2.2", | ||
"@polymer/gen-typescript-declarations": "^1.5.1" | ||
"webmat": "^0.2.2" | ||
}, | ||
@@ -29,3 +29,3 @@ "scripts": { | ||
}, | ||
"version": "3.0.2", | ||
"version": "3.1.0", | ||
"main": "iron-fit-behavior.js", | ||
@@ -32,0 +32,0 @@ "author": "The Polymer Authors", |
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
51793
1008
0