Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.iml
node_modules/
build/
coverage/
21 changes: 13 additions & 8 deletions lib/utils/domFns.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,35 +68,40 @@
}
}

export function outerHeight(node: HTMLElement): number {
export function outerHeight(node: Element): number {
// This is deliberately excluding margin for our calculations, since we are using
// offsetTop which is including margin. See getBoundPosition
let height = node.clientHeight;
// Use clientHeight for HTMLElements (faster), getBoundingClientRect for SVG
let height = (node: any).clientHeight ?? Math.round(node.getBoundingClientRect().height);
const computedStyle = node.ownerDocument.defaultView.getComputedStyle(node);
height += int(computedStyle.borderTopWidth);
height += int(computedStyle.borderBottomWidth);
return height;
}

export function outerWidth(node: HTMLElement): number {
export function outerWidth(node: Element): number {
// This is deliberately excluding margin for our calculations, since we are using
// offsetLeft which is including margin. See getBoundPosition
let width = node.clientWidth;
// Use clientWidth for HTMLElements (faster), getBoundingClientRect for SVG
let width = (node: any).clientWidth ?? Math.round(node.getBoundingClientRect().width);
const computedStyle = node.ownerDocument.defaultView.getComputedStyle(node);
width += int(computedStyle.borderLeftWidth);
width += int(computedStyle.borderRightWidth);
return width;
}
export function innerHeight(node: HTMLElement): number {
let height = node.clientHeight;

export function innerHeight(node: Element): number {
// Use clientHeight for HTMLElements (faster), getBoundingClientRect for SVG
let height = (node: any).clientHeight ?? Math.round(node.getBoundingClientRect().height);
const computedStyle = node.ownerDocument.defaultView.getComputedStyle(node);
height -= int(computedStyle.paddingTop);
height -= int(computedStyle.paddingBottom);
return height;
}

export function innerWidth(node: HTMLElement): number {
let width = node.clientWidth;
export function innerWidth(node: Element): number {
// Use clientWidth for HTMLElements (faster), getBoundingClientRect for SVG
let width = (node: any).clientWidth ?? Math.round(node.getBoundingClientRect().width);
const computedStyle = node.ownerDocument.defaultView.getComputedStyle(node);
width -= int(computedStyle.paddingLeft);
width -= int(computedStyle.paddingRight);
Expand Down Expand Up @@ -193,7 +198,7 @@
selection.removeAllRanges();
}
}
} catch (e) {

Check warning on line 201 in lib/utils/domFns.js

View workflow job for this annotation

GitHub Actions / lint

'e' is defined but never used
// probably IE
}
}
Expand Down
28 changes: 22 additions & 6 deletions lib/utils/positionFns.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,35 @@ export function getBoundPosition(draggable: Draggable, x: number, y: number): [n
boundNode = rootNode.querySelector(bounds);
}

if (!(boundNode instanceof ownerWindow.HTMLElement)) {
// Accept Element (not just HTMLElement) to support SVG elements
if (!(boundNode instanceof ownerWindow.Element)) {
throw new Error('Bounds selector "' + bounds + '" could not find an element.');
}
const boundNodeEl: HTMLElement = boundNode; // for Flow, can't seem to refine correctly
const boundNodeEl: Element = boundNode; // for Flow, can't seem to refine correctly
const nodeStyle = ownerWindow.getComputedStyle(node);
const boundNodeStyle = ownerWindow.getComputedStyle(boundNodeEl);

// Calculate node offset. HTMLElements have offsetLeft/offsetTop, but SVG elements don't.
// For SVG elements, compute offset from bounding rectangles.
let nodeOffsetLeft: number, nodeOffsetTop: number;
if (node instanceof ownerWindow.HTMLElement) {
nodeOffsetLeft = node.offsetLeft;
nodeOffsetTop = node.offsetTop;
} else {
// For SVG elements, calculate offset relative to parent using getBoundingClientRect
const nodeRect = node.getBoundingClientRect();
const boundNodeRect = boundNodeEl.getBoundingClientRect();
nodeOffsetLeft = nodeRect.left - boundNodeRect.left - int(boundNodeStyle.borderLeftWidth);
nodeOffsetTop = nodeRect.top - boundNodeRect.top - int(boundNodeStyle.borderTopWidth);
}

// Compute bounds. This is a pain with padding and offsets but this gets it exactly right.
bounds = {
left: -node.offsetLeft + int(boundNodeStyle.paddingLeft) + int(nodeStyle.marginLeft),
top: -node.offsetTop + int(boundNodeStyle.paddingTop) + int(nodeStyle.marginTop),
right: innerWidth(boundNodeEl) - outerWidth(node) - node.offsetLeft +
left: -nodeOffsetLeft + int(boundNodeStyle.paddingLeft) + int(nodeStyle.marginLeft),
top: -nodeOffsetTop + int(boundNodeStyle.paddingTop) + int(nodeStyle.marginTop),
right: innerWidth(boundNodeEl) - outerWidth(node) - nodeOffsetLeft +
int(boundNodeStyle.paddingRight) - int(nodeStyle.marginRight),
bottom: innerHeight(boundNodeEl) - outerHeight(node) - node.offsetTop +
bottom: innerHeight(boundNodeEl) - outerHeight(node) - nodeOffsetTop +
int(boundNodeStyle.paddingBottom) - int(nodeStyle.marginBottom)
};
}
Expand Down
Loading