diff --git a/src/cdk/drag-drop/directives/drag.spec.ts b/src/cdk/drag-drop/directives/drag.spec.ts index 85b97a61ebf4..35f0f9183011 100644 --- a/src/cdk/drag-drop/directives/drag.spec.ts +++ b/src/cdk/drag-drop/directives/drag.spec.ts @@ -86,27 +86,6 @@ describe('CdkDrag', () => { expect(dragElement.style.transform).toBe('translate3d(50px, 100px, 0px)'); })); - it('should drag an SVG element freely to a particular position', fakeAsync(() => { - const fixture = createComponent(StandaloneDraggableSvg); - fixture.detectChanges(); - const dragElement = fixture.componentInstance.dragElement.nativeElement; - - expect(dragElement.getAttribute('transform')).toBeFalsy(); - dragElementViaMouse(fixture, dragElement, 50, 100); - expect(dragElement.getAttribute('transform')).toBe('translate(50 100)'); - })); - - it('should drag an SVG element freely to a particular position in SVG viewBox coordinates', - fakeAsync(() => { - const fixture = createComponent(StandaloneDraggableSvgWithViewBox); - fixture.detectChanges(); - const dragElement = fixture.componentInstance.dragElement.nativeElement; - - expect(dragElement.getAttribute('transform')).toBeFalsy(); - dragElementViaMouse(fixture, dragElement, 50, 100); - expect(dragElement.getAttribute('transform')).toBe('translate(100 200)'); - })); - it('should drag an element freely to a particular position when the page is scrolled', fakeAsync(() => { const fixture = createComponent(StandaloneDraggable); @@ -5959,32 +5938,6 @@ class StandaloneDraggableWithOnPush { @ViewChild(CdkDrag) dragInstance: CdkDrag; } -@Component({ - template: ` - - - - ` -}) -class StandaloneDraggableSvg { - @ViewChild('dragElement') dragElement: ElementRef; -} - -@Component({ - template: ` - - - - ` -}) -class StandaloneDraggableSvgWithViewBox { - @ViewChild('dragElement') dragElement: ElementRef; -} - @Component({ template: `
implements AfterViewInit, OnChanges, OnDestroy { private _updateRootElement() { const element = this.element.nativeElement; const rootElement = this.rootElementSelector ? - getClosestMatchingAncestor(element, this.rootElementSelector) : element; + element.closest(this.rootElementSelector) : element; if (rootElement && (typeof ngDevMode === 'undefined' || ngDevMode)) { assertElementNode(rootElement, 'cdkDrag'); @@ -373,7 +373,7 @@ export class CdkDrag implements AfterViewInit, OnChanges, OnDestroy { } if (typeof boundary === 'string') { - return getClosestMatchingAncestor(this.element.nativeElement, boundary); + return this.element.nativeElement.closest(boundary); } const element = coerceElement(boundary); @@ -434,8 +434,7 @@ export class CdkDrag implements AfterViewInit, OnChanges, OnDestroy { // the item was projected into another item by something like `ngTemplateOutlet`. let parent = this.element.nativeElement.parentElement; while (parent) { - // `classList` needs to be null checked, because IE doesn't have it on some elements. - if (parent.classList?.contains(DRAG_HOST_CLASS)) { + if (parent.classList.contains(DRAG_HOST_CLASS)) { ref.withParent(CdkDrag._dragInstances.find(drag => { return drag.element.nativeElement === parent; })?._dragRef || null); @@ -538,21 +537,3 @@ export class CdkDrag implements AfterViewInit, OnChanges, OnDestroy { static ngAcceptInputType_disabled: BooleanInput; } - -/** Gets the closest ancestor of an element that matches a selector. */ -function getClosestMatchingAncestor(element: HTMLElement, selector: string) { - let currentElement = element.parentElement as HTMLElement | null; - - while (currentElement) { - // IE doesn't support `matches` so we have to fall back to `msMatchesSelector`. - if (currentElement.matches ? currentElement.matches(selector) : - (currentElement as any).msMatchesSelector(selector)) { - return currentElement; - } - - currentElement = currentElement.parentElement; - } - - return null; -} - diff --git a/src/cdk/drag-drop/drag-ref.ts b/src/cdk/drag-drop/drag-ref.ts index 37e2a64f7d92..00bfee9bf35e 100644 --- a/src/cdk/drag-drop/drag-ref.ts +++ b/src/cdk/drag-drop/drag-ref.ts @@ -715,12 +715,6 @@ export class DragRef { constrainedPointerPosition.y - this._pickupPositionOnPage.y + this._passiveTransform.y; this._applyRootElementTransform(activeTransform.x, activeTransform.y); - - // Apply transform as attribute if dragging and svg element to work for IE - if (typeof SVGElement !== 'undefined' && this._rootElement instanceof SVGElement) { - const appliedTransform = `translate(${activeTransform.x} ${activeTransform.y})`; - this._rootElement.setAttribute('transform', appliedTransform); - } } // Since this event gets fired for every pixel while dragging, we only @@ -1274,21 +1268,20 @@ export class DragRef { */ private _applyRootElementTransform(x: number, y: number) { const transform = getTransform(x, y); + const styles = this._rootElement.style; // Cache the previous transform amount only after the first drag sequence, because // we don't want our own transforms to stack on top of each other. // Should be excluded none because none + translate3d(x, y, x) is invalid css if (this._initialTransform == null) { - this._initialTransform = this._rootElement.style.transform - && this._rootElement.style.transform != 'none' - ? this._rootElement.style.transform - : ''; + this._initialTransform = + styles.transform && styles.transform != 'none' ? styles.transform : ''; } // Preserve the previous `transform` value, if there was one. Note that we apply our own // transform before the user's, because things like rotation can affect which direction // the element will be translated towards. - this._rootElement.style.transform = combineTransforms(transform, this._initialTransform); + styles.transform = combineTransforms(transform, this._initialTransform); } /** @@ -1403,11 +1396,9 @@ export class DragRef { if (scrollDifference) { const target = _getEventTarget(event)!; - // ClientRect dimensions are based on the scroll position of the page and its parent node so - // we have to update the cached boundary ClientRect if the user has scrolled. Check for - // the `document` specifically since IE doesn't support `contains` on it. - if (this._boundaryRect && (target === this._document || - (target !== this._boundaryElement && target.contains(this._boundaryElement)))) { + // ClientRect dimensions are based on the scroll position of the page and its parent + // node so we have to update the cached boundary ClientRect if the user has scrolled. + if (this._boundaryRect && target.contains(this._boundaryElement)) { adjustClientRect(this._boundaryRect, scrollDifference.top, scrollDifference.left); } diff --git a/src/cdk/drag-drop/drop-list-ref.ts b/src/cdk/drag-drop/drop-list-ref.ts index 60db591fef39..9aa46ba3fb7b 100644 --- a/src/cdk/drag-drop/drop-list-ref.ts +++ b/src/cdk/drag-drop/drop-list-ref.ts @@ -434,7 +434,7 @@ export class DropListRef { const items = this._orientation === 'horizontal' && this._direction === 'rtl' ? this._itemPositions.slice().reverse() : this._itemPositions; - return findIndex(items, currentItem => currentItem.drag === item); + return items.findIndex(currentItem => currentItem.drag === item); } /** @@ -468,7 +468,7 @@ export class DropListRef { } const isHorizontal = this._orientation === 'horizontal'; - const currentIndex = findIndex(siblings, currentItem => currentItem.drag === item); + const currentIndex = siblings.findIndex(currentItem => currentItem.drag === item); const siblingAtNewPosition = siblings[newIndex]; const currentPosition = siblings[currentIndex].clientRect; const newPosition = siblingAtNewPosition.clientRect; @@ -754,7 +754,7 @@ export class DropListRef { private _getItemIndexFromPointerPosition(item: DragRef, pointerX: number, pointerY: number, delta?: {x: number, y: number}): number { const isHorizontal = this._orientation === 'horizontal'; - const index = findIndex(this._itemPositions, ({drag, clientRect}, _, array) => { + const index = this._itemPositions.findIndex(({drag, clientRect}, _, array) => { if (drag === item) { // If there's only one item left in the container, it must be // the dragged item itself so we use it as a reference. @@ -801,15 +801,15 @@ export class DropListRef { const scrollStep = this.autoScrollStep; if (this._verticalScrollDirection === AutoScrollVerticalDirection.UP) { - incrementVerticalScroll(node, -scrollStep); + node.scrollBy(0, -scrollStep); } else if (this._verticalScrollDirection === AutoScrollVerticalDirection.DOWN) { - incrementVerticalScroll(node, scrollStep); + node.scrollBy(0, scrollStep); } if (this._horizontalScrollDirection === AutoScrollHorizontalDirection.LEFT) { - incrementHorizontalScroll(node, -scrollStep); + node.scrollBy(-scrollStep, 0); } else if (this._horizontalScrollDirection === AutoScrollHorizontalDirection.RIGHT) { - incrementHorizontalScroll(node, scrollStep); + node.scrollBy(scrollStep, 0); } }); } @@ -953,52 +953,6 @@ export class DropListRef { } -/** - * Finds the index of an item that matches a predicate function. Used as an equivalent - * of `Array.prototype.findIndex` which isn't part of the standard Google typings. - * @param array Array in which to look for matches. - * @param predicate Function used to determine whether an item is a match. - */ -function findIndex(array: T[], - predicate: (value: T, index: number, obj: T[]) => boolean): number { - - for (let i = 0; i < array.length; i++) { - if (predicate(array[i], i, array)) { - return i; - } - } - - return -1; -} - -/** - * Increments the vertical scroll position of a node. - * @param node Node whose scroll position should change. - * @param amount Amount of pixels that the `node` should be scrolled. - */ -function incrementVerticalScroll(node: HTMLElement | Window, amount: number) { - if (node === window) { - (node as Window).scrollBy(0, amount); - } else { - // Ideally we could use `Element.scrollBy` here as well, but IE and Edge don't support it. - (node as HTMLElement).scrollTop += amount; - } -} - -/** - * Increments the horizontal scroll position of a node. - * @param node Node whose scroll position should change. - * @param amount Amount of pixels that the `node` should be scrolled. - */ -function incrementHorizontalScroll(node: HTMLElement | Window, amount: number) { - if (node === window) { - (node as Window).scrollBy(amount, 0); - } else { - // Ideally we could use `Element.scrollBy` here as well, but IE and Edge don't support it. - (node as HTMLElement).scrollLeft += amount; - } -} - /** * Gets whether the vertical auto-scroll direction of a node. * @param clientRect Dimensions of the node. diff --git a/src/cdk/drag-drop/parent-position-tracker.ts b/src/cdk/drag-drop/parent-position-tracker.ts index 9c7a165c9f4e..35735f8ce565 100644 --- a/src/cdk/drag-drop/parent-position-tracker.ts +++ b/src/cdk/drag-drop/parent-position-tracker.ts @@ -55,10 +55,6 @@ export class ParentPositionTracker { return null; } - // Used when figuring out whether an element is inside the scroll parent. If the scrolled - // parent is the `document`, we use the `documentElement`, because IE doesn't support - // `contains` on the `document`. - const scrolledParentNode = target === this._document ? target.documentElement : target; const scrollPosition = cachedPosition.scrollPosition; let newTop: number; let newLeft: number; @@ -78,7 +74,7 @@ export class ParentPositionTracker { // Go through and update the cached positions of the scroll // parents that are inside the element that was scrolled. this.positions.forEach((position, node) => { - if (position.clientRect && target !== node && scrolledParentNode.contains(node)) { + if (position.clientRect && target !== node && target.contains(node)) { adjustClientRect(position.clientRect, topDifference, leftDifference); } });