diff --git a/projects/angular-grid-layout/src/lib/grid-item/grid-item.component.ts b/projects/angular-grid-layout/src/lib/grid-item/grid-item.component.ts index 0df45bd..0a4e3be 100644 --- a/projects/angular-grid-layout/src/lib/grid-item/grid-item.component.ts +++ b/projects/angular-grid-layout/src/lib/grid-item/grid-item.component.ts @@ -2,17 +2,17 @@ import { AfterContentInit, ChangeDetectionStrategy, Component, ContentChild, ContentChildren, ElementRef, Inject, Input, NgZone, OnDestroy, OnInit, QueryList, Renderer2, ViewChild } from '@angular/core'; -import { BehaviorSubject, iif, merge, NEVER, Observable, Subject, Subscription } from 'rxjs'; -import { exhaustMap, filter, map, startWith, switchMap, take, takeUntil } from 'rxjs/operators'; -import { ktdPointerDown, ktdPointerUp, ktdPointerClient } from '../utils/pointer.utils'; -import { GRID_ITEM_GET_RENDER_DATA_TOKEN, KtdGridItemRenderDataTokenType } from '../grid.definitions'; +import { BehaviorSubject, NEVER, Observable, Subject, Subscription, iif, merge } from 'rxjs'; +import { exhaustMap, filter, map, startWith, switchMap, take, takeUntil, tap } from 'rxjs/operators'; +import { BooleanInput, coerceBooleanProperty } from '../coercion/boolean-property'; +import { NumberInput, coerceNumberProperty } from '../coercion/number-property'; import { KTD_GRID_DRAG_HANDLE, KtdGridDragHandle } from '../directives/drag-handle'; +import { KTD_GRID_ITEM_PLACEHOLDER, KtdGridItemPlaceholder } from '../directives/placeholder'; import { KTD_GRID_RESIZE_HANDLE, KtdGridResizeHandle } from '../directives/resize-handle'; +import { GRID_ITEM_GET_RENDER_DATA_TOKEN, KtdGridItemRenderDataTokenType } from '../grid.definitions'; import { KtdGridService } from '../grid.service'; import { ktdOutsideZone } from '../utils/operators'; -import { BooleanInput, coerceBooleanProperty } from '../coercion/boolean-property'; -import { coerceNumberProperty, NumberInput } from '../coercion/number-property'; -import { KTD_GRID_ITEM_PLACEHOLDER, KtdGridItemPlaceholder } from '../directives/placeholder'; +import { ktdIsMouseEventOrMousePointerEvent, ktdPointerClient, ktdPointerDown, ktdPointerUp } from '../utils/pointer.utils'; @Component({ standalone: true, @@ -171,9 +171,9 @@ export class KtdGridItemComponent implements OnInit, OnDestroy, AfterContentInit // with our own dragging (e.g. `img` tags do it by default). Prevent the default action // to stop it from happening. Note that preventing on `dragstart` also seems to work, but // it's flaky and it fails if the user drags it away quickly. Also note that we only want - // to do this for `mousedown` since doing the same for `touchstart` will stop any `click` - // events from firing on touch devices. - if (startEvent.target && (startEvent.target as HTMLElement).draggable && startEvent.type === 'mousedown') { + // to do this for `mousedown` and `pointerdown` since doing the same for `touchstart` will + // stop any `click` events from firing on touch devices. + if (ktdIsMouseEventOrMousePointerEvent(startEvent)) { startEvent.preventDefault(); } @@ -216,6 +216,11 @@ export class KtdGridItemComponent implements OnInit, OnDestroy, AfterContentInit this.renderer.setStyle(this.resizeElem.nativeElement, 'display', 'block'); return ktdPointerDown(this.resizeElem.nativeElement); } + }), + tap((startEvent) => { + if (ktdIsMouseEventOrMousePointerEvent(startEvent)) { + startEvent.preventDefault(); + } }) ); } diff --git a/projects/angular-grid-layout/src/lib/utils/pointer.utils.ts b/projects/angular-grid-layout/src/lib/utils/pointer.utils.ts index cccc6e8..45bd146 100644 --- a/projects/angular-grid-layout/src/lib/utils/pointer.utils.ts +++ b/projects/angular-grid-layout/src/lib/utils/pointer.utils.ts @@ -50,6 +50,11 @@ export function ktdPointerClient(event: MouseEvent | TouchEvent): { clientX: num }; } +export function ktdIsMouseEventOrMousePointerEvent(event: MouseEvent | TouchEvent | PointerEvent): boolean { + return event.type === 'mousedown' + || (event.type === 'pointerdown' && (event as PointerEvent).pointerType === 'mouse'); +} + /** Returns true if browser supports pointer events */ export function ktdSupportsPointerEvents(): boolean { return !!window.PointerEvent; @@ -84,7 +89,7 @@ function ktdMouseOrTouchDown(element, touchNumber = 1): Observable { +function ktdMouseOrTouchMove(element: HTMLElement, touchNumber = 1): Observable { return iif( () => ktdIsMobileOrTablet(), fromEvent(element, 'touchmove', activeEventListenerOptions as AddEventListenerOptions).pipe( @@ -128,7 +133,7 @@ export function ktdPointerDown(element): Observable(element, 'pointerdown', passiveEventListenerOptions as AddEventListenerOptions).pipe( + return fromEvent(element, 'pointerdown', activeEventListenerOptions as AddEventListenerOptions).pipe( filter((pointerEvent) => pointerEvent.isPrimary) ) } @@ -139,7 +144,7 @@ export function ktdPointerDown(element): Observable { if (!ktdSupportsPointerEvents()) { - return ktdMouserOrTouchMove(element); + return ktdMouseOrTouchMove(element); } return fromEvent(element, 'pointermove', activeEventListenerOptions as AddEventListenerOptions).pipe( filter((pointerEvent) => pointerEvent.isPrimary), diff --git a/projects/demo-app/src/app/real-life-example/table-sorting/table-sorting.component.scss b/projects/demo-app/src/app/real-life-example/table-sorting/table-sorting.component.scss index bac579c..383e1e3 100644 --- a/projects/demo-app/src/app/real-life-example/table-sorting/table-sorting.component.scss +++ b/projects/demo-app/src/app/real-life-example/table-sorting/table-sorting.component.scss @@ -3,6 +3,7 @@ width: 100%; height: 100%; overflow-y: auto; + touch-action: none; // This is needed to make drag and drop on touch devices possible without interfering with the inner scroll. } table {