Skip to content

Commit 0980b6e

Browse files
authored
refactor(cdk/drag-drop): clean up IE workarounds (#23293)
Cleans up the various workarounds that were put in place for IE.
1 parent d83e5cf commit 0980b6e

File tree

5 files changed

+18
-143
lines changed

5 files changed

+18
-143
lines changed

src/cdk/drag-drop/directives/drag.spec.ts

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -86,27 +86,6 @@ describe('CdkDrag', () => {
8686
expect(dragElement.style.transform).toBe('translate3d(50px, 100px, 0px)');
8787
}));
8888

89-
it('should drag an SVG element freely to a particular position', fakeAsync(() => {
90-
const fixture = createComponent(StandaloneDraggableSvg);
91-
fixture.detectChanges();
92-
const dragElement = fixture.componentInstance.dragElement.nativeElement;
93-
94-
expect(dragElement.getAttribute('transform')).toBeFalsy();
95-
dragElementViaMouse(fixture, dragElement, 50, 100);
96-
expect(dragElement.getAttribute('transform')).toBe('translate(50 100)');
97-
}));
98-
99-
it('should drag an SVG element freely to a particular position in SVG viewBox coordinates',
100-
fakeAsync(() => {
101-
const fixture = createComponent(StandaloneDraggableSvgWithViewBox);
102-
fixture.detectChanges();
103-
const dragElement = fixture.componentInstance.dragElement.nativeElement;
104-
105-
expect(dragElement.getAttribute('transform')).toBeFalsy();
106-
dragElementViaMouse(fixture, dragElement, 50, 100);
107-
expect(dragElement.getAttribute('transform')).toBe('translate(100 200)');
108-
}));
109-
11089
it('should drag an element freely to a particular position when the page is scrolled',
11190
fakeAsync(() => {
11291
const fixture = createComponent(StandaloneDraggable);
@@ -5959,32 +5938,6 @@ class StandaloneDraggableWithOnPush {
59595938
@ViewChild(CdkDrag) dragInstance: CdkDrag;
59605939
}
59615940

5962-
@Component({
5963-
template: `
5964-
<svg><g
5965-
cdkDrag
5966-
#dragElement>
5967-
<circle fill="red" r="50" cx="50" cy="50"/>
5968-
</g></svg>
5969-
`
5970-
})
5971-
class StandaloneDraggableSvg {
5972-
@ViewChild('dragElement') dragElement: ElementRef<SVGElement>;
5973-
}
5974-
5975-
@Component({
5976-
template: `
5977-
<svg width="400px" height="400px" viewBox="0 0 800 800"><g
5978-
cdkDrag
5979-
#dragElement>
5980-
<circle fill="red" r="50" cx="50" cy="50"/>
5981-
</g></svg>
5982-
`
5983-
})
5984-
class StandaloneDraggableSvgWithViewBox {
5985-
@ViewChild('dragElement') dragElement: ElementRef<SVGElement>;
5986-
}
5987-
59885941
@Component({
59895942
template: `
59905943
<div #dragElement cdkDrag [cdkDragDisabled]="draggingDisabled"

src/cdk/drag-drop/directives/drag.ts

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
355355
private _updateRootElement() {
356356
const element = this.element.nativeElement;
357357
const rootElement = this.rootElementSelector ?
358-
getClosestMatchingAncestor(element, this.rootElementSelector) : element;
358+
element.closest<HTMLElement>(this.rootElementSelector) : element;
359359

360360
if (rootElement && (typeof ngDevMode === 'undefined' || ngDevMode)) {
361361
assertElementNode(rootElement, 'cdkDrag');
@@ -373,7 +373,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
373373
}
374374

375375
if (typeof boundary === 'string') {
376-
return getClosestMatchingAncestor(this.element.nativeElement, boundary);
376+
return this.element.nativeElement.closest<HTMLElement>(boundary);
377377
}
378378

379379
const element = coerceElement(boundary);
@@ -434,8 +434,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
434434
// the item was projected into another item by something like `ngTemplateOutlet`.
435435
let parent = this.element.nativeElement.parentElement;
436436
while (parent) {
437-
// `classList` needs to be null checked, because IE doesn't have it on some elements.
438-
if (parent.classList?.contains(DRAG_HOST_CLASS)) {
437+
if (parent.classList.contains(DRAG_HOST_CLASS)) {
439438
ref.withParent(CdkDrag._dragInstances.find(drag => {
440439
return drag.element.nativeElement === parent;
441440
})?._dragRef || null);
@@ -538,21 +537,3 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
538537

539538
static ngAcceptInputType_disabled: BooleanInput;
540539
}
541-
542-
/** Gets the closest ancestor of an element that matches a selector. */
543-
function getClosestMatchingAncestor(element: HTMLElement, selector: string) {
544-
let currentElement = element.parentElement as HTMLElement | null;
545-
546-
while (currentElement) {
547-
// IE doesn't support `matches` so we have to fall back to `msMatchesSelector`.
548-
if (currentElement.matches ? currentElement.matches(selector) :
549-
(currentElement as any).msMatchesSelector(selector)) {
550-
return currentElement;
551-
}
552-
553-
currentElement = currentElement.parentElement;
554-
}
555-
556-
return null;
557-
}
558-

src/cdk/drag-drop/drag-ref.ts

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -715,12 +715,6 @@ export class DragRef<T = any> {
715715
constrainedPointerPosition.y - this._pickupPositionOnPage.y + this._passiveTransform.y;
716716

717717
this._applyRootElementTransform(activeTransform.x, activeTransform.y);
718-
719-
// Apply transform as attribute if dragging and svg element to work for IE
720-
if (typeof SVGElement !== 'undefined' && this._rootElement instanceof SVGElement) {
721-
const appliedTransform = `translate(${activeTransform.x} ${activeTransform.y})`;
722-
this._rootElement.setAttribute('transform', appliedTransform);
723-
}
724718
}
725719

726720
// Since this event gets fired for every pixel while dragging, we only
@@ -1274,21 +1268,20 @@ export class DragRef<T = any> {
12741268
*/
12751269
private _applyRootElementTransform(x: number, y: number) {
12761270
const transform = getTransform(x, y);
1271+
const styles = this._rootElement.style;
12771272

12781273
// Cache the previous transform amount only after the first drag sequence, because
12791274
// we don't want our own transforms to stack on top of each other.
12801275
// Should be excluded none because none + translate3d(x, y, x) is invalid css
12811276
if (this._initialTransform == null) {
1282-
this._initialTransform = this._rootElement.style.transform
1283-
&& this._rootElement.style.transform != 'none'
1284-
? this._rootElement.style.transform
1285-
: '';
1277+
this._initialTransform =
1278+
styles.transform && styles.transform != 'none' ? styles.transform : '';
12861279
}
12871280

12881281
// Preserve the previous `transform` value, if there was one. Note that we apply our own
12891282
// transform before the user's, because things like rotation can affect which direction
12901283
// the element will be translated towards.
1291-
this._rootElement.style.transform = combineTransforms(transform, this._initialTransform);
1284+
styles.transform = combineTransforms(transform, this._initialTransform);
12921285
}
12931286

12941287
/**
@@ -1403,11 +1396,9 @@ export class DragRef<T = any> {
14031396
if (scrollDifference) {
14041397
const target = _getEventTarget<HTMLElement|Document>(event)!;
14051398

1406-
// ClientRect dimensions are based on the scroll position of the page and its parent node so
1407-
// we have to update the cached boundary ClientRect if the user has scrolled. Check for
1408-
// the `document` specifically since IE doesn't support `contains` on it.
1409-
if (this._boundaryRect && (target === this._document ||
1410-
(target !== this._boundaryElement && target.contains(this._boundaryElement)))) {
1399+
// ClientRect dimensions are based on the scroll position of the page and its parent
1400+
// node so we have to update the cached boundary ClientRect if the user has scrolled.
1401+
if (this._boundaryRect && target.contains(this._boundaryElement)) {
14111402
adjustClientRect(this._boundaryRect, scrollDifference.top, scrollDifference.left);
14121403
}
14131404

src/cdk/drag-drop/drop-list-ref.ts

Lines changed: 7 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ export class DropListRef<T = any> {
434434
const items = this._orientation === 'horizontal' && this._direction === 'rtl' ?
435435
this._itemPositions.slice().reverse() : this._itemPositions;
436436

437-
return findIndex(items, currentItem => currentItem.drag === item);
437+
return items.findIndex(currentItem => currentItem.drag === item);
438438
}
439439

440440
/**
@@ -468,7 +468,7 @@ export class DropListRef<T = any> {
468468
}
469469

470470
const isHorizontal = this._orientation === 'horizontal';
471-
const currentIndex = findIndex(siblings, currentItem => currentItem.drag === item);
471+
const currentIndex = siblings.findIndex(currentItem => currentItem.drag === item);
472472
const siblingAtNewPosition = siblings[newIndex];
473473
const currentPosition = siblings[currentIndex].clientRect;
474474
const newPosition = siblingAtNewPosition.clientRect;
@@ -754,7 +754,7 @@ export class DropListRef<T = any> {
754754
private _getItemIndexFromPointerPosition(item: DragRef, pointerX: number, pointerY: number,
755755
delta?: {x: number, y: number}): number {
756756
const isHorizontal = this._orientation === 'horizontal';
757-
const index = findIndex(this._itemPositions, ({drag, clientRect}, _, array) => {
757+
const index = this._itemPositions.findIndex(({drag, clientRect}, _, array) => {
758758
if (drag === item) {
759759
// If there's only one item left in the container, it must be
760760
// the dragged item itself so we use it as a reference.
@@ -801,15 +801,15 @@ export class DropListRef<T = any> {
801801
const scrollStep = this.autoScrollStep;
802802

803803
if (this._verticalScrollDirection === AutoScrollVerticalDirection.UP) {
804-
incrementVerticalScroll(node, -scrollStep);
804+
node.scrollBy(0, -scrollStep);
805805
} else if (this._verticalScrollDirection === AutoScrollVerticalDirection.DOWN) {
806-
incrementVerticalScroll(node, scrollStep);
806+
node.scrollBy(0, scrollStep);
807807
}
808808

809809
if (this._horizontalScrollDirection === AutoScrollHorizontalDirection.LEFT) {
810-
incrementHorizontalScroll(node, -scrollStep);
810+
node.scrollBy(-scrollStep, 0);
811811
} else if (this._horizontalScrollDirection === AutoScrollHorizontalDirection.RIGHT) {
812-
incrementHorizontalScroll(node, scrollStep);
812+
node.scrollBy(scrollStep, 0);
813813
}
814814
});
815815
}
@@ -953,52 +953,6 @@ export class DropListRef<T = any> {
953953
}
954954

955955

956-
/**
957-
* Finds the index of an item that matches a predicate function. Used as an equivalent
958-
* of `Array.prototype.findIndex` which isn't part of the standard Google typings.
959-
* @param array Array in which to look for matches.
960-
* @param predicate Function used to determine whether an item is a match.
961-
*/
962-
function findIndex<T>(array: T[],
963-
predicate: (value: T, index: number, obj: T[]) => boolean): number {
964-
965-
for (let i = 0; i < array.length; i++) {
966-
if (predicate(array[i], i, array)) {
967-
return i;
968-
}
969-
}
970-
971-
return -1;
972-
}
973-
974-
/**
975-
* Increments the vertical scroll position of a node.
976-
* @param node Node whose scroll position should change.
977-
* @param amount Amount of pixels that the `node` should be scrolled.
978-
*/
979-
function incrementVerticalScroll(node: HTMLElement | Window, amount: number) {
980-
if (node === window) {
981-
(node as Window).scrollBy(0, amount);
982-
} else {
983-
// Ideally we could use `Element.scrollBy` here as well, but IE and Edge don't support it.
984-
(node as HTMLElement).scrollTop += amount;
985-
}
986-
}
987-
988-
/**
989-
* Increments the horizontal scroll position of a node.
990-
* @param node Node whose scroll position should change.
991-
* @param amount Amount of pixels that the `node` should be scrolled.
992-
*/
993-
function incrementHorizontalScroll(node: HTMLElement | Window, amount: number) {
994-
if (node === window) {
995-
(node as Window).scrollBy(amount, 0);
996-
} else {
997-
// Ideally we could use `Element.scrollBy` here as well, but IE and Edge don't support it.
998-
(node as HTMLElement).scrollLeft += amount;
999-
}
1000-
}
1001-
1002956
/**
1003957
* Gets whether the vertical auto-scroll direction of a node.
1004958
* @param clientRect Dimensions of the node.

src/cdk/drag-drop/parent-position-tracker.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,6 @@ export class ParentPositionTracker {
5555
return null;
5656
}
5757

58-
// Used when figuring out whether an element is inside the scroll parent. If the scrolled
59-
// parent is the `document`, we use the `documentElement`, because IE doesn't support
60-
// `contains` on the `document`.
61-
const scrolledParentNode = target === this._document ? target.documentElement : target;
6258
const scrollPosition = cachedPosition.scrollPosition;
6359
let newTop: number;
6460
let newLeft: number;
@@ -78,7 +74,7 @@ export class ParentPositionTracker {
7874
// Go through and update the cached positions of the scroll
7975
// parents that are inside the element that was scrolled.
8076
this.positions.forEach((position, node) => {
81-
if (position.clientRect && target !== node && scrolledParentNode.contains(node)) {
77+
if (position.clientRect && target !== node && target.contains(node)) {
8278
adjustClientRect(position.clientRect, topDifference, leftDifference);
8379
}
8480
});

0 commit comments

Comments
 (0)