From 1303d8f0617141bbe56ad4082adbbfe10b14ff63 Mon Sep 17 00:00:00 2001 From: Jeroen Zwartepoorte Date: Thu, 12 Mar 2020 22:12:54 +0100 Subject: [PATCH] fix(cdk/overlay): support SVG element as overlay origin (#18595) * Support SVG elements as overlay origin. * Review. * Cleanup. * Missing semicolon. * Review. * Remove describe. * Rename. Co-authored-by: Jeroen Zwartepoorte (cherry picked from commit 09f54767ea0a7c94caab2f248c4110273418d7d1) --- ...exible-connected-position-strategy.spec.ts | 34 +++++++++++++++++-- .../flexible-connected-position-strategy.ts | 3 +- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts b/src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts index e6b5c2656b97..966787dc8dd7 100644 --- a/src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts +++ b/src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts @@ -767,6 +767,29 @@ describe('FlexibleConnectedPositionStrategy', () => { }); + it('should position the panel correctly when the origin is an SVG element', () => { + document.body.removeChild(originElement); + originElement = createBlockElement('svg', 'http://www.w3.org/2000/svg'); + document.body.appendChild(originElement); + + const originRect = originElement.getBoundingClientRect(); + + positionStrategy + .setOrigin(originElement) + .withPositions([{ + originX: 'start', + originY: 'bottom', + overlayX: 'start', + overlayY: 'top' + }]); + + attachOverlay({positionStrategy}); + + const overlayRect = overlayRef.overlayElement.getBoundingClientRect(); + expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect.bottom)); + expect(Math.floor(overlayRect.left)).toBe(Math.floor(originRect.left)); + }); + it('should account for the `offsetX` pushing the overlay out of the screen', () => { // Position the element so it would have enough space to fit. originElement.style.top = '200px'; @@ -2592,8 +2615,15 @@ function createPositionedBlockElement() { } /** Creates a block element with a default size. */ -function createBlockElement() { - const element = document.createElement('div'); +function createBlockElement(tagName = 'div', namespace?: string) { + let element; + + if (namespace) { + element = document.createElementNS(namespace, tagName) as HTMLElement; + } else { + element = document.createElement(tagName); + } + element.style.width = `${DEFAULT_WIDTH}px`; element.style.height = `${DEFAULT_HEIGHT}px`; element.style.backgroundColor = 'rebeccapurple'; diff --git a/src/cdk/overlay/position/flexible-connected-position-strategy.ts b/src/cdk/overlay/position/flexible-connected-position-strategy.ts index 18121cd9ef44..9a9793a0553b 100644 --- a/src/cdk/overlay/position/flexible-connected-position-strategy.ts +++ b/src/cdk/overlay/position/flexible-connected-position-strategy.ts @@ -1110,7 +1110,8 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy { return origin.nativeElement.getBoundingClientRect(); } - if (origin instanceof HTMLElement) { + // Check for Element so SVG elements are also supported. + if (origin instanceof Element) { return origin.getBoundingClientRect(); }