in src/cdk/drag-drop/drag-ref.ts [843:918]
private _initializeDragSequence(referenceElement: HTMLElement, event: MouseEvent | TouchEvent) {
// Stop propagation if the item is inside another
// draggable so we don't start multiple drag sequences.
if (this._parentDragRef) {
event.stopPropagation();
}
const isDragging = this.isDragging();
const isTouchSequence = isTouchEvent(event);
const isAuxiliaryMouseButton = !isTouchSequence && (event as MouseEvent).button !== 0;
const rootElement = this._rootElement;
const target = _getEventTarget(event);
const isSyntheticEvent =
!isTouchSequence &&
this._lastTouchEventTime &&
this._lastTouchEventTime + MOUSE_EVENT_IGNORE_TIME > Date.now();
const isFakeEvent = isTouchSequence
? isFakeTouchstartFromScreenReader(event as TouchEvent)
: isFakeMousedownFromScreenReader(event as MouseEvent);
// If the event started from an element with the native HTML drag&drop, it'll interfere
// 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 (target && (target as HTMLElement).draggable && event.type === 'mousedown') {
event.preventDefault();
}
// Abort if the user is already dragging or is using a mouse button other than the primary one.
if (isDragging || isAuxiliaryMouseButton || isSyntheticEvent || isFakeEvent) {
return;
}
// If we've got handles, we need to disable the tap highlight on the entire root element,
// otherwise iOS will still add it, even though all the drag interactions on the handle
// are disabled.
if (this._handles.length) {
const rootStyles = rootElement.style as DragCSSStyleDeclaration;
this._rootElementTapHighlight = rootStyles.webkitTapHighlightColor || '';
rootStyles.webkitTapHighlightColor = 'transparent';
}
this._hasStartedDragging = this._hasMoved = false;
// Avoid multiple subscriptions and memory leaks when multi touch
// (isDragging check above isn't enough because of possible temporal and/or dimensional delays)
this._removeSubscriptions();
this._pointerMoveSubscription = this._dragDropRegistry.pointerMove.subscribe(this._pointerMove);
this._pointerUpSubscription = this._dragDropRegistry.pointerUp.subscribe(this._pointerUp);
this._scrollSubscription = this._dragDropRegistry
.scrolled(this._getShadowRoot())
.subscribe(scrollEvent => this._updateOnScroll(scrollEvent));
if (this._boundaryElement) {
this._boundaryRect = getMutableClientRect(this._boundaryElement);
}
// If we have a custom preview we can't know ahead of time how large it'll be so we position
// it next to the cursor. The exception is when the consumer has opted into making the preview
// the same size as the root element, in which case we do know the size.
const previewTemplate = this._previewTemplate;
this._pickupPositionInElement =
previewTemplate && previewTemplate.template && !previewTemplate.matchSize
? {x: 0, y: 0}
: this._getPointerPositionInElement(referenceElement, event);
const pointerPosition =
(this._pickupPositionOnPage =
this._lastKnownPointerPosition =
this._getPointerPositionOnPage(event));
this._pointerDirectionDelta = {x: 0, y: 0};
this._pointerPositionAtLastDirectionChange = {x: pointerPosition.x, y: pointerPosition.y};
this._dragStartTime = Date.now();
this._dragDropRegistry.startDragging(this, event);
}