UNPKG

46.5 kBJavaScriptView Raw
1import { Subject, Observable, merge, ReplaySubject, combineLatest, fromEvent } from 'rxjs';
2import { DOCUMENT } from '@angular/common';
3import autoScroll from '@mattlewis92/dom-autoscroller';
4import { __read, __assign } from 'tslib';
5import { Injectable, Directive, ElementRef, Input, NgModule, defineInjectable, EventEmitter, Renderer2, NgZone, ViewContainerRef, Optional, Inject, Output } from '@angular/core';
6import { map, mergeMap, takeUntil, take, takeLast, pairwise, share, filter, count, startWith, distinctUntilChanged } from 'rxjs/operators';
7
8/**
9 * @fileoverview added by tsickle
10 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
11 */
12var DraggableHelper = /** @class */ (function () {
13 function DraggableHelper() {
14 this.currentDrag = new Subject();
15 }
16 DraggableHelper.decorators = [
17 { type: Injectable, args: [{
18 providedIn: 'root',
19 },] }
20 ];
21 /** @nocollapse */ DraggableHelper.ngInjectableDef = defineInjectable({ factory: function DraggableHelper_Factory() { return new DraggableHelper(); }, token: DraggableHelper, providedIn: "root" });
22 return DraggableHelper;
23}());
24
25/**
26 * @fileoverview added by tsickle
27 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
28 */
29/**
30 * If the window isn't scrollable, then place this on the scrollable container that draggable elements are inside. e.g.
31 * ```html
32 * <div style="overflow: scroll" mwlDraggableScrollContainer>
33 * <div mwlDraggable>Drag me!</div>
34 * </div>
35 * ```
36 */
37var DraggableScrollContainerDirective = /** @class */ (function () {
38 /**
39 * @hidden
40 */
41 function DraggableScrollContainerDirective(elementRef) {
42 this.elementRef = elementRef;
43 /**
44 * Trigger the DragStart after a long touch in scrollable container when true
45 * @deprecated will be removed in v5 (use [touchStartLongPress]="{delay: 300, delta: 30}" on the mwlDraggable element instead)
46 */
47 this.activeLongPressDrag = false;
48 /**
49 * Configuration of a long touch
50 * Duration in ms of a long touch before activating DragStart
51 * Delta of the
52 * @deprecated will be removed in v5 (use [touchStartLongPress]="{delay: 300, delta: 30}" on the mwlDraggable element instead)
53 */
54 this.longPressConfig = { duration: 300, delta: 30 };
55 }
56 DraggableScrollContainerDirective.decorators = [
57 { type: Directive, args: [{
58 selector: '[mwlDraggableScrollContainer]',
59 },] }
60 ];
61 /** @nocollapse */
62 DraggableScrollContainerDirective.ctorParameters = function () { return [
63 { type: ElementRef }
64 ]; };
65 DraggableScrollContainerDirective.propDecorators = {
66 activeLongPressDrag: [{ type: Input }],
67 longPressConfig: [{ type: Input }]
68 };
69 return DraggableScrollContainerDirective;
70}());
71
72/**
73 * @fileoverview added by tsickle
74 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
75 */
76/**
77 * @param {?} renderer
78 * @param {?} element
79 * @param {?} classToAdd
80 * @return {?}
81 */
82function addClass(renderer, element, classToAdd) {
83 if (classToAdd) {
84 classToAdd
85 .split(' ')
86 .forEach((/**
87 * @param {?} className
88 * @return {?}
89 */
90 function (className) {
91 return renderer.addClass(element.nativeElement, className);
92 }));
93 }
94}
95/**
96 * @param {?} renderer
97 * @param {?} element
98 * @param {?} classToRemove
99 * @return {?}
100 */
101function removeClass(renderer, element, classToRemove) {
102 if (classToRemove) {
103 classToRemove
104 .split(' ')
105 .forEach((/**
106 * @param {?} className
107 * @return {?}
108 */
109 function (className) {
110 return renderer.removeClass(element.nativeElement, className);
111 }));
112 }
113}
114
115/**
116 * @fileoverview added by tsickle
117 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
118 */
119var DraggableDirective = /** @class */ (function () {
120 /**
121 * @hidden
122 */
123 function DraggableDirective(element, renderer, draggableHelper, zone, vcr, scrollContainer, document) {
124 this.element = element;
125 this.renderer = renderer;
126 this.draggableHelper = draggableHelper;
127 this.zone = zone;
128 this.vcr = vcr;
129 this.scrollContainer = scrollContainer;
130 this.document = document;
131 /**
132 * The axis along which the element is draggable
133 */
134 this.dragAxis = { x: true, y: true };
135 /**
136 * Snap all drags to an x / y grid
137 */
138 this.dragSnapGrid = {};
139 /**
140 * Show a ghost element that shows the drag when dragging
141 */
142 this.ghostDragEnabled = true;
143 /**
144 * Show the original element when ghostDragEnabled is true
145 */
146 this.showOriginalElementWhileDragging = false;
147 /**
148 * The cursor to use when hovering over a draggable element
149 */
150 this.dragCursor = '';
151 /*
152 * Options used to control the behaviour of auto scrolling: https://www.npmjs.com/package/dom-autoscroller
153 */
154 this.autoScroll = {
155 margin: 20,
156 };
157 /**
158 * Called when the element can be dragged along one axis and has the mouse or pointer device pressed on it
159 */
160 this.dragPointerDown = new EventEmitter();
161 /**
162 * Called when the element has started to be dragged.
163 * Only called after at least one mouse or touch move event.
164 * If you call $event.cancelDrag$.emit() it will cancel the current drag
165 */
166 this.dragStart = new EventEmitter();
167 /**
168 * Called after the ghost element has been created
169 */
170 this.ghostElementCreated = new EventEmitter();
171 /**
172 * Called when the element is being dragged
173 */
174 this.dragging = new EventEmitter();
175 /**
176 * Called after the element is dragged
177 */
178 this.dragEnd = new EventEmitter();
179 /**
180 * @hidden
181 */
182 this.pointerDown$ = new Subject();
183 /**
184 * @hidden
185 */
186 this.pointerMove$ = new Subject();
187 /**
188 * @hidden
189 */
190 this.pointerUp$ = new Subject();
191 this.eventListenerSubscriptions = {};
192 this.destroy$ = new Subject();
193 this.timeLongPress = { timerBegin: 0, timerEnd: 0 };
194 }
195 /**
196 * @return {?}
197 */
198 DraggableDirective.prototype.ngOnInit = /**
199 * @return {?}
200 */
201 function () {
202 var _this = this;
203 this.checkEventListeners();
204 /** @type {?} */
205 var pointerDragged$ = this.pointerDown$.pipe(filter((/**
206 * @return {?}
207 */
208 function () { return _this.canDrag(); })), mergeMap((/**
209 * @param {?} pointerDownEvent
210 * @return {?}
211 */
212 function (pointerDownEvent) {
213 // fix for https://github.com/mattlewis92/angular-draggable-droppable/issues/61
214 // stop mouse events propagating up the chain
215 if (pointerDownEvent.event.stopPropagation && !_this.scrollContainer) {
216 pointerDownEvent.event.stopPropagation();
217 }
218 // hack to prevent text getting selected in safari while dragging
219 /** @type {?} */
220 var globalDragStyle = _this.renderer.createElement('style');
221 _this.renderer.setAttribute(globalDragStyle, 'type', 'text/css');
222 _this.renderer.appendChild(globalDragStyle, _this.renderer.createText("\n body * {\n -moz-user-select: none;\n -ms-user-select: none;\n -webkit-user-select: none;\n user-select: none;\n }\n "));
223 requestAnimationFrame((/**
224 * @return {?}
225 */
226 function () {
227 _this.document.head.appendChild(globalDragStyle);
228 }));
229 /** @type {?} */
230 var startScrollPosition = _this.getScrollPosition();
231 /** @type {?} */
232 var scrollContainerScroll$ = new Observable((/**
233 * @param {?} observer
234 * @return {?}
235 */
236 function (observer) {
237 /** @type {?} */
238 var scrollContainer = _this.scrollContainer
239 ? _this.scrollContainer.elementRef.nativeElement
240 : 'window';
241 return _this.renderer.listen(scrollContainer, 'scroll', (/**
242 * @param {?} e
243 * @return {?}
244 */
245 function (e) {
246 return observer.next(e);
247 }));
248 })).pipe(startWith(startScrollPosition), map((/**
249 * @return {?}
250 */
251 function () { return _this.getScrollPosition(); })));
252 /** @type {?} */
253 var currentDrag$ = new Subject();
254 /** @type {?} */
255 var cancelDrag$ = new ReplaySubject();
256 _this.zone.run((/**
257 * @return {?}
258 */
259 function () {
260 _this.dragPointerDown.next({ x: 0, y: 0 });
261 }));
262 /** @type {?} */
263 var dragComplete$ = merge(_this.pointerUp$, _this.pointerDown$, cancelDrag$, _this.destroy$).pipe(share());
264 /** @type {?} */
265 var pointerMove = combineLatest([
266 _this.pointerMove$,
267 scrollContainerScroll$,
268 ]).pipe(map((/**
269 * @param {?} __0
270 * @return {?}
271 */
272 function (_a) {
273 var _b = __read(_a, 2), pointerMoveEvent = _b[0], scroll = _b[1];
274 return {
275 currentDrag$: currentDrag$,
276 transformX: pointerMoveEvent.clientX - pointerDownEvent.clientX,
277 transformY: pointerMoveEvent.clientY - pointerDownEvent.clientY,
278 clientX: pointerMoveEvent.clientX,
279 clientY: pointerMoveEvent.clientY,
280 scrollLeft: scroll.left,
281 scrollTop: scroll.top,
282 target: pointerMoveEvent.event.target,
283 };
284 })), map((/**
285 * @param {?} moveData
286 * @return {?}
287 */
288 function (moveData) {
289 if (_this.dragSnapGrid.x) {
290 moveData.transformX =
291 Math.round(moveData.transformX / _this.dragSnapGrid.x) *
292 _this.dragSnapGrid.x;
293 }
294 if (_this.dragSnapGrid.y) {
295 moveData.transformY =
296 Math.round(moveData.transformY / _this.dragSnapGrid.y) *
297 _this.dragSnapGrid.y;
298 }
299 return moveData;
300 })), map((/**
301 * @param {?} moveData
302 * @return {?}
303 */
304 function (moveData) {
305 if (!_this.dragAxis.x) {
306 moveData.transformX = 0;
307 }
308 if (!_this.dragAxis.y) {
309 moveData.transformY = 0;
310 }
311 return moveData;
312 })), map((/**
313 * @param {?} moveData
314 * @return {?}
315 */
316 function (moveData) {
317 /** @type {?} */
318 var scrollX = moveData.scrollLeft - startScrollPosition.left;
319 /** @type {?} */
320 var scrollY = moveData.scrollTop - startScrollPosition.top;
321 return __assign({}, moveData, { x: moveData.transformX + scrollX, y: moveData.transformY + scrollY });
322 })), filter((/**
323 * @param {?} __0
324 * @return {?}
325 */
326 function (_a) {
327 var x = _a.x, y = _a.y, transformX = _a.transformX, transformY = _a.transformY;
328 return !_this.validateDrag ||
329 _this.validateDrag({
330 x: x,
331 y: y,
332 transform: { x: transformX, y: transformY },
333 });
334 })), takeUntil(dragComplete$), share());
335 /** @type {?} */
336 var dragStarted$ = pointerMove.pipe(take(1), share());
337 /** @type {?} */
338 var dragEnded$ = pointerMove.pipe(takeLast(1), share());
339 dragStarted$.subscribe((/**
340 * @param {?} __0
341 * @return {?}
342 */
343 function (_a) {
344 var clientX = _a.clientX, clientY = _a.clientY, x = _a.x, y = _a.y;
345 _this.zone.run((/**
346 * @return {?}
347 */
348 function () {
349 _this.dragStart.next({ cancelDrag$: cancelDrag$ });
350 }));
351 _this.scroller = autoScroll([
352 _this.scrollContainer
353 ? _this.scrollContainer.elementRef.nativeElement
354 : _this.document.defaultView,
355 ], __assign({}, _this.autoScroll, { autoScroll: /**
356 * @return {?}
357 */
358 function () {
359 return true;
360 } }));
361 addClass(_this.renderer, _this.element, _this.dragActiveClass);
362 if (_this.ghostDragEnabled) {
363 /** @type {?} */
364 var rect = _this.element.nativeElement.getBoundingClientRect();
365 /** @type {?} */
366 var clone_1 = (/** @type {?} */ (_this.element.nativeElement.cloneNode(true)));
367 if (!_this.showOriginalElementWhileDragging) {
368 _this.renderer.setStyle(_this.element.nativeElement, 'visibility', 'hidden');
369 }
370 if (_this.ghostElementAppendTo) {
371 _this.ghostElementAppendTo.appendChild(clone_1);
372 }
373 else {
374 (/** @type {?} */ (_this.element.nativeElement.parentNode)).insertBefore(clone_1, _this.element.nativeElement.nextSibling);
375 }
376 _this.ghostElement = clone_1;
377 _this.document.body.style.cursor = _this.dragCursor;
378 _this.setElementStyles(clone_1, {
379 position: 'fixed',
380 top: rect.top + "px",
381 left: rect.left + "px",
382 width: rect.width + "px",
383 height: rect.height + "px",
384 cursor: _this.dragCursor,
385 margin: '0',
386 willChange: 'transform',
387 pointerEvents: 'none',
388 });
389 if (_this.ghostElementTemplate) {
390 /** @type {?} */
391 var viewRef_1 = _this.vcr.createEmbeddedView(_this.ghostElementTemplate);
392 clone_1.innerHTML = '';
393 viewRef_1.rootNodes
394 .filter((/**
395 * @param {?} node
396 * @return {?}
397 */
398 function (node) { return node instanceof Node; }))
399 .forEach((/**
400 * @param {?} node
401 * @return {?}
402 */
403 function (node) {
404 clone_1.appendChild(node);
405 }));
406 dragEnded$.subscribe((/**
407 * @return {?}
408 */
409 function () {
410 _this.vcr.remove(_this.vcr.indexOf(viewRef_1));
411 }));
412 }
413 _this.zone.run((/**
414 * @return {?}
415 */
416 function () {
417 _this.ghostElementCreated.emit({
418 clientX: clientX - x,
419 clientY: clientY - y,
420 element: clone_1,
421 });
422 }));
423 dragEnded$.subscribe((/**
424 * @return {?}
425 */
426 function () {
427 (/** @type {?} */ (clone_1.parentElement)).removeChild(clone_1);
428 _this.ghostElement = null;
429 _this.renderer.setStyle(_this.element.nativeElement, 'visibility', '');
430 }));
431 }
432 _this.draggableHelper.currentDrag.next(currentDrag$);
433 }));
434 dragEnded$
435 .pipe(mergeMap((/**
436 * @param {?} dragEndData
437 * @return {?}
438 */
439 function (dragEndData) {
440 /** @type {?} */
441 var dragEndData$ = cancelDrag$.pipe(count(), take(1), map((/**
442 * @param {?} calledCount
443 * @return {?}
444 */
445 function (calledCount) { return (__assign({}, dragEndData, { dragCancelled: calledCount > 0 })); })));
446 cancelDrag$.complete();
447 return dragEndData$;
448 })))
449 .subscribe((/**
450 * @param {?} __0
451 * @return {?}
452 */
453 function (_a) {
454 var x = _a.x, y = _a.y, dragCancelled = _a.dragCancelled;
455 _this.scroller.destroy();
456 _this.zone.run((/**
457 * @return {?}
458 */
459 function () {
460 _this.dragEnd.next({ x: x, y: y, dragCancelled: dragCancelled });
461 }));
462 removeClass(_this.renderer, _this.element, _this.dragActiveClass);
463 currentDrag$.complete();
464 }));
465 merge(dragComplete$, dragEnded$)
466 .pipe(take(1))
467 .subscribe((/**
468 * @return {?}
469 */
470 function () {
471 requestAnimationFrame((/**
472 * @return {?}
473 */
474 function () {
475 _this.document.head.removeChild(globalDragStyle);
476 }));
477 }));
478 return pointerMove;
479 })), share());
480 merge(pointerDragged$.pipe(take(1), map((/**
481 * @param {?} value
482 * @return {?}
483 */
484 function (value) { return [, value]; }))), pointerDragged$.pipe(pairwise()))
485 .pipe(filter((/**
486 * @param {?} __0
487 * @return {?}
488 */
489 function (_a) {
490 var _b = __read(_a, 2), previous = _b[0], next = _b[1];
491 if (!previous) {
492 return true;
493 }
494 return previous.x !== next.x || previous.y !== next.y;
495 })), map((/**
496 * @param {?} __0
497 * @return {?}
498 */
499 function (_a) {
500 var _b = __read(_a, 2), previous = _b[0], next = _b[1];
501 return next;
502 })))
503 .subscribe((/**
504 * @param {?} __0
505 * @return {?}
506 */
507 function (_a) {
508 var x = _a.x, y = _a.y, currentDrag$ = _a.currentDrag$, clientX = _a.clientX, clientY = _a.clientY, transformX = _a.transformX, transformY = _a.transformY, target = _a.target;
509 _this.zone.run((/**
510 * @return {?}
511 */
512 function () {
513 _this.dragging.next({ x: x, y: y });
514 }));
515 requestAnimationFrame((/**
516 * @return {?}
517 */
518 function () {
519 if (_this.ghostElement) {
520 /** @type {?} */
521 var transform = "translate3d(" + transformX + "px, " + transformY + "px, 0px)";
522 _this.setElementStyles(_this.ghostElement, {
523 transform: transform,
524 '-webkit-transform': transform,
525 '-ms-transform': transform,
526 '-moz-transform': transform,
527 '-o-transform': transform,
528 });
529 }
530 }));
531 currentDrag$.next({
532 clientX: clientX,
533 clientY: clientY,
534 dropData: _this.dropData,
535 target: target,
536 });
537 }));
538 };
539 /**
540 * @param {?} changes
541 * @return {?}
542 */
543 DraggableDirective.prototype.ngOnChanges = /**
544 * @param {?} changes
545 * @return {?}
546 */
547 function (changes) {
548 if (changes.dragAxis) {
549 this.checkEventListeners();
550 }
551 };
552 /**
553 * @return {?}
554 */
555 DraggableDirective.prototype.ngOnDestroy = /**
556 * @return {?}
557 */
558 function () {
559 this.unsubscribeEventListeners();
560 this.pointerDown$.complete();
561 this.pointerMove$.complete();
562 this.pointerUp$.complete();
563 this.destroy$.next();
564 };
565 /**
566 * @private
567 * @return {?}
568 */
569 DraggableDirective.prototype.checkEventListeners = /**
570 * @private
571 * @return {?}
572 */
573 function () {
574 var _this = this;
575 /** @type {?} */
576 var canDrag = this.canDrag();
577 /** @type {?} */
578 var hasEventListeners = Object.keys(this.eventListenerSubscriptions).length > 0;
579 if (canDrag && !hasEventListeners) {
580 this.zone.runOutsideAngular((/**
581 * @return {?}
582 */
583 function () {
584 _this.eventListenerSubscriptions.mousedown = _this.renderer.listen(_this.element.nativeElement, 'mousedown', (/**
585 * @param {?} event
586 * @return {?}
587 */
588 function (event) {
589 _this.onMouseDown(event);
590 }));
591 _this.eventListenerSubscriptions.mouseup = _this.renderer.listen('document', 'mouseup', (/**
592 * @param {?} event
593 * @return {?}
594 */
595 function (event) {
596 _this.onMouseUp(event);
597 }));
598 _this.eventListenerSubscriptions.touchstart = _this.renderer.listen(_this.element.nativeElement, 'touchstart', (/**
599 * @param {?} event
600 * @return {?}
601 */
602 function (event) {
603 _this.onTouchStart(event);
604 }));
605 _this.eventListenerSubscriptions.touchend = _this.renderer.listen('document', 'touchend', (/**
606 * @param {?} event
607 * @return {?}
608 */
609 function (event) {
610 _this.onTouchEnd(event);
611 }));
612 _this.eventListenerSubscriptions.touchcancel = _this.renderer.listen('document', 'touchcancel', (/**
613 * @param {?} event
614 * @return {?}
615 */
616 function (event) {
617 _this.onTouchEnd(event);
618 }));
619 _this.eventListenerSubscriptions.mouseenter = _this.renderer.listen(_this.element.nativeElement, 'mouseenter', (/**
620 * @return {?}
621 */
622 function () {
623 _this.onMouseEnter();
624 }));
625 _this.eventListenerSubscriptions.mouseleave = _this.renderer.listen(_this.element.nativeElement, 'mouseleave', (/**
626 * @return {?}
627 */
628 function () {
629 _this.onMouseLeave();
630 }));
631 }));
632 }
633 else if (!canDrag && hasEventListeners) {
634 this.unsubscribeEventListeners();
635 }
636 };
637 /**
638 * @private
639 * @param {?} event
640 * @return {?}
641 */
642 DraggableDirective.prototype.onMouseDown = /**
643 * @private
644 * @param {?} event
645 * @return {?}
646 */
647 function (event) {
648 var _this = this;
649 if (event.button === 0) {
650 if (!this.eventListenerSubscriptions.mousemove) {
651 this.eventListenerSubscriptions.mousemove = this.renderer.listen('document', 'mousemove', (/**
652 * @param {?} mouseMoveEvent
653 * @return {?}
654 */
655 function (mouseMoveEvent) {
656 _this.pointerMove$.next({
657 event: mouseMoveEvent,
658 clientX: mouseMoveEvent.clientX,
659 clientY: mouseMoveEvent.clientY,
660 });
661 }));
662 }
663 this.pointerDown$.next({
664 event: event,
665 clientX: event.clientX,
666 clientY: event.clientY,
667 });
668 }
669 };
670 /**
671 * @private
672 * @param {?} event
673 * @return {?}
674 */
675 DraggableDirective.prototype.onMouseUp = /**
676 * @private
677 * @param {?} event
678 * @return {?}
679 */
680 function (event) {
681 if (event.button === 0) {
682 if (this.eventListenerSubscriptions.mousemove) {
683 this.eventListenerSubscriptions.mousemove();
684 delete this.eventListenerSubscriptions.mousemove;
685 }
686 this.pointerUp$.next({
687 event: event,
688 clientX: event.clientX,
689 clientY: event.clientY,
690 });
691 }
692 };
693 /**
694 * @private
695 * @param {?} event
696 * @return {?}
697 */
698 DraggableDirective.prototype.onTouchStart = /**
699 * @private
700 * @param {?} event
701 * @return {?}
702 */
703 function (event) {
704 var _this = this;
705 /** @type {?} */
706 var startScrollPosition;
707 /** @type {?} */
708 var isDragActivated;
709 /** @type {?} */
710 var hasContainerScrollbar;
711 if ((this.scrollContainer && this.scrollContainer.activeLongPressDrag) ||
712 this.touchStartLongPress) {
713 this.timeLongPress.timerBegin = Date.now();
714 isDragActivated = false;
715 hasContainerScrollbar = this.hasScrollbar();
716 startScrollPosition = this.getScrollPosition();
717 }
718 if (!this.eventListenerSubscriptions.touchmove) {
719 /** @type {?} */
720 var contextMenuListener_1 = fromEvent(this.document, 'contextmenu').subscribe((/**
721 * @param {?} e
722 * @return {?}
723 */
724 function (e) {
725 e.preventDefault();
726 }));
727 /** @type {?} */
728 var touchMoveListener_1 = fromEvent(this.document, 'touchmove', {
729 passive: false,
730 }).subscribe((/**
731 * @param {?} touchMoveEvent
732 * @return {?}
733 */
734 function (touchMoveEvent) {
735 if (((_this.scrollContainer && _this.scrollContainer.activeLongPressDrag) ||
736 _this.touchStartLongPress) &&
737 !isDragActivated &&
738 hasContainerScrollbar) {
739 isDragActivated = _this.shouldBeginDrag(event, touchMoveEvent, startScrollPosition);
740 }
741 if (((!_this.scrollContainer ||
742 !_this.scrollContainer.activeLongPressDrag) &&
743 !_this.touchStartLongPress) ||
744 !hasContainerScrollbar ||
745 isDragActivated) {
746 touchMoveEvent.preventDefault();
747 _this.pointerMove$.next({
748 event: touchMoveEvent,
749 clientX: touchMoveEvent.targetTouches[0].clientX,
750 clientY: touchMoveEvent.targetTouches[0].clientY,
751 });
752 }
753 }));
754 this.eventListenerSubscriptions.touchmove = (/**
755 * @return {?}
756 */
757 function () {
758 contextMenuListener_1.unsubscribe();
759 touchMoveListener_1.unsubscribe();
760 });
761 }
762 this.pointerDown$.next({
763 event: event,
764 clientX: event.touches[0].clientX,
765 clientY: event.touches[0].clientY,
766 });
767 };
768 /**
769 * @private
770 * @param {?} event
771 * @return {?}
772 */
773 DraggableDirective.prototype.onTouchEnd = /**
774 * @private
775 * @param {?} event
776 * @return {?}
777 */
778 function (event) {
779 if (this.eventListenerSubscriptions.touchmove) {
780 this.eventListenerSubscriptions.touchmove();
781 delete this.eventListenerSubscriptions.touchmove;
782 if ((this.scrollContainer && this.scrollContainer.activeLongPressDrag) ||
783 this.touchStartLongPress) {
784 this.enableScroll();
785 }
786 }
787 this.pointerUp$.next({
788 event: event,
789 clientX: event.changedTouches[0].clientX,
790 clientY: event.changedTouches[0].clientY,
791 });
792 };
793 /**
794 * @private
795 * @return {?}
796 */
797 DraggableDirective.prototype.onMouseEnter = /**
798 * @private
799 * @return {?}
800 */
801 function () {
802 this.setCursor(this.dragCursor);
803 };
804 /**
805 * @private
806 * @return {?}
807 */
808 DraggableDirective.prototype.onMouseLeave = /**
809 * @private
810 * @return {?}
811 */
812 function () {
813 this.setCursor('');
814 };
815 /**
816 * @private
817 * @return {?}
818 */
819 DraggableDirective.prototype.canDrag = /**
820 * @private
821 * @return {?}
822 */
823 function () {
824 return this.dragAxis.x || this.dragAxis.y;
825 };
826 /**
827 * @private
828 * @param {?} value
829 * @return {?}
830 */
831 DraggableDirective.prototype.setCursor = /**
832 * @private
833 * @param {?} value
834 * @return {?}
835 */
836 function (value) {
837 if (!this.eventListenerSubscriptions.mousemove) {
838 this.renderer.setStyle(this.element.nativeElement, 'cursor', value);
839 }
840 };
841 /**
842 * @private
843 * @return {?}
844 */
845 DraggableDirective.prototype.unsubscribeEventListeners = /**
846 * @private
847 * @return {?}
848 */
849 function () {
850 var _this = this;
851 Object.keys(this.eventListenerSubscriptions).forEach((/**
852 * @param {?} type
853 * @return {?}
854 */
855 function (type) {
856 ((/** @type {?} */ (_this))).eventListenerSubscriptions[type]();
857 delete ((/** @type {?} */ (_this))).eventListenerSubscriptions[type];
858 }));
859 };
860 /**
861 * @private
862 * @param {?} element
863 * @param {?} styles
864 * @return {?}
865 */
866 DraggableDirective.prototype.setElementStyles = /**
867 * @private
868 * @param {?} element
869 * @param {?} styles
870 * @return {?}
871 */
872 function (element, styles) {
873 var _this = this;
874 Object.keys(styles).forEach((/**
875 * @param {?} key
876 * @return {?}
877 */
878 function (key) {
879 _this.renderer.setStyle(element, key, styles[key]);
880 }));
881 };
882 /**
883 * @private
884 * @return {?}
885 */
886 DraggableDirective.prototype.getScrollElement = /**
887 * @private
888 * @return {?}
889 */
890 function () {
891 if (this.scrollContainer) {
892 return this.scrollContainer.elementRef.nativeElement;
893 }
894 else {
895 return this.document.body;
896 }
897 };
898 /**
899 * @private
900 * @return {?}
901 */
902 DraggableDirective.prototype.getScrollPosition = /**
903 * @private
904 * @return {?}
905 */
906 function () {
907 if (this.scrollContainer) {
908 return {
909 top: this.scrollContainer.elementRef.nativeElement.scrollTop,
910 left: this.scrollContainer.elementRef.nativeElement.scrollLeft,
911 };
912 }
913 else {
914 return {
915 top: window.pageYOffset || this.document.documentElement.scrollTop,
916 left: window.pageXOffset || this.document.documentElement.scrollLeft,
917 };
918 }
919 };
920 /**
921 * @private
922 * @param {?} event
923 * @param {?} touchMoveEvent
924 * @param {?} startScrollPosition
925 * @return {?}
926 */
927 DraggableDirective.prototype.shouldBeginDrag = /**
928 * @private
929 * @param {?} event
930 * @param {?} touchMoveEvent
931 * @param {?} startScrollPosition
932 * @return {?}
933 */
934 function (event, touchMoveEvent, startScrollPosition) {
935 /** @type {?} */
936 var moveScrollPosition = this.getScrollPosition();
937 /** @type {?} */
938 var deltaScroll = {
939 top: Math.abs(moveScrollPosition.top - startScrollPosition.top),
940 left: Math.abs(moveScrollPosition.left - startScrollPosition.left),
941 };
942 /** @type {?} */
943 var deltaX = Math.abs(touchMoveEvent.targetTouches[0].clientX - event.touches[0].clientX) - deltaScroll.left;
944 /** @type {?} */
945 var deltaY = Math.abs(touchMoveEvent.targetTouches[0].clientY - event.touches[0].clientY) - deltaScroll.top;
946 /** @type {?} */
947 var deltaTotal = deltaX + deltaY;
948 /** @type {?} */
949 var longPressConfig = this.touchStartLongPress
950 ? this.touchStartLongPress
951 : /* istanbul ignore next */
952 {
953 delta: this.scrollContainer.longPressConfig.delta,
954 delay: this.scrollContainer.longPressConfig.duration,
955 };
956 if (deltaTotal > longPressConfig.delta ||
957 deltaScroll.top > 0 ||
958 deltaScroll.left > 0) {
959 this.timeLongPress.timerBegin = Date.now();
960 }
961 this.timeLongPress.timerEnd = Date.now();
962 /** @type {?} */
963 var duration = this.timeLongPress.timerEnd - this.timeLongPress.timerBegin;
964 if (duration >= longPressConfig.delay) {
965 this.disableScroll();
966 return true;
967 }
968 return false;
969 };
970 /**
971 * @private
972 * @return {?}
973 */
974 DraggableDirective.prototype.enableScroll = /**
975 * @private
976 * @return {?}
977 */
978 function () {
979 if (this.scrollContainer) {
980 this.renderer.setStyle(this.scrollContainer.elementRef.nativeElement, 'overflow', '');
981 }
982 this.renderer.setStyle(this.document.body, 'overflow', '');
983 };
984 /**
985 * @private
986 * @return {?}
987 */
988 DraggableDirective.prototype.disableScroll = /**
989 * @private
990 * @return {?}
991 */
992 function () {
993 /* istanbul ignore next */
994 if (this.scrollContainer) {
995 this.renderer.setStyle(this.scrollContainer.elementRef.nativeElement, 'overflow', 'hidden');
996 }
997 this.renderer.setStyle(this.document.body, 'overflow', 'hidden');
998 };
999 /**
1000 * @private
1001 * @return {?}
1002 */
1003 DraggableDirective.prototype.hasScrollbar = /**
1004 * @private
1005 * @return {?}
1006 */
1007 function () {
1008 /** @type {?} */
1009 var scrollContainer = this.getScrollElement();
1010 /** @type {?} */
1011 var containerHasHorizontalScroll = scrollContainer.scrollWidth > scrollContainer.clientWidth;
1012 /** @type {?} */
1013 var containerHasVerticalScroll = scrollContainer.scrollHeight > scrollContainer.clientHeight;
1014 return containerHasHorizontalScroll || containerHasVerticalScroll;
1015 };
1016 DraggableDirective.decorators = [
1017 { type: Directive, args: [{
1018 selector: '[mwlDraggable]',
1019 },] }
1020 ];
1021 /** @nocollapse */
1022 DraggableDirective.ctorParameters = function () { return [
1023 { type: ElementRef },
1024 { type: Renderer2 },
1025 { type: DraggableHelper },
1026 { type: NgZone },
1027 { type: ViewContainerRef },
1028 { type: DraggableScrollContainerDirective, decorators: [{ type: Optional }] },
1029 { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
1030 ]; };
1031 DraggableDirective.propDecorators = {
1032 dropData: [{ type: Input }],
1033 dragAxis: [{ type: Input }],
1034 dragSnapGrid: [{ type: Input }],
1035 ghostDragEnabled: [{ type: Input }],
1036 showOriginalElementWhileDragging: [{ type: Input }],
1037 validateDrag: [{ type: Input }],
1038 dragCursor: [{ type: Input }],
1039 dragActiveClass: [{ type: Input }],
1040 ghostElementAppendTo: [{ type: Input }],
1041 ghostElementTemplate: [{ type: Input }],
1042 touchStartLongPress: [{ type: Input }],
1043 autoScroll: [{ type: Input }],
1044 dragPointerDown: [{ type: Output }],
1045 dragStart: [{ type: Output }],
1046 ghostElementCreated: [{ type: Output }],
1047 dragging: [{ type: Output }],
1048 dragEnd: [{ type: Output }]
1049 };
1050 return DraggableDirective;
1051}());
1052
1053/**
1054 * @fileoverview added by tsickle
1055 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
1056 */
1057/**
1058 * @param {?} clientX
1059 * @param {?} clientY
1060 * @param {?} rect
1061 * @return {?}
1062 */
1063function isCoordinateWithinRectangle(clientX, clientY, rect) {
1064 return (clientX >= rect.left &&
1065 clientX <= rect.right &&
1066 clientY >= rect.top &&
1067 clientY <= rect.bottom);
1068}
1069var DroppableDirective = /** @class */ (function () {
1070 function DroppableDirective(element, draggableHelper, zone, renderer, scrollContainer) {
1071 this.element = element;
1072 this.draggableHelper = draggableHelper;
1073 this.zone = zone;
1074 this.renderer = renderer;
1075 this.scrollContainer = scrollContainer;
1076 /**
1077 * Called when a draggable element starts overlapping the element
1078 */
1079 this.dragEnter = new EventEmitter();
1080 /**
1081 * Called when a draggable element stops overlapping the element
1082 */
1083 this.dragLeave = new EventEmitter();
1084 /**
1085 * Called when a draggable element is moved over the element
1086 */
1087 this.dragOver = new EventEmitter();
1088 /**
1089 * Called when a draggable element is dropped on this element
1090 */
1091 this.drop = new EventEmitter(); // tslint:disable-line no-output-named-after-standard-event
1092 }
1093 /**
1094 * @return {?}
1095 */
1096 DroppableDirective.prototype.ngOnInit = /**
1097 * @return {?}
1098 */
1099 function () {
1100 var _this = this;
1101 this.currentDragSubscription = this.draggableHelper.currentDrag.subscribe((/**
1102 * @param {?} drag$
1103 * @return {?}
1104 */
1105 function (drag$) {
1106 addClass(_this.renderer, _this.element, _this.dragActiveClass);
1107 /** @type {?} */
1108 var droppableElement = {
1109 updateCache: true,
1110 };
1111 /** @type {?} */
1112 var deregisterScrollListener = _this.renderer.listen(_this.scrollContainer
1113 ? _this.scrollContainer.elementRef.nativeElement
1114 : 'window', 'scroll', (/**
1115 * @return {?}
1116 */
1117 function () {
1118 droppableElement.updateCache = true;
1119 }));
1120 /** @type {?} */
1121 var currentDragDropData;
1122 /** @type {?} */
1123 var overlaps$ = drag$.pipe(map((/**
1124 * @param {?} __0
1125 * @return {?}
1126 */
1127 function (_a) {
1128 var clientX = _a.clientX, clientY = _a.clientY, dropData = _a.dropData, target = _a.target;
1129 currentDragDropData = dropData;
1130 if (droppableElement.updateCache) {
1131 droppableElement.rect = _this.element.nativeElement.getBoundingClientRect();
1132 if (_this.scrollContainer) {
1133 droppableElement.scrollContainerRect = _this.scrollContainer.elementRef.nativeElement.getBoundingClientRect();
1134 }
1135 droppableElement.updateCache = false;
1136 }
1137 /** @type {?} */
1138 var isWithinElement = isCoordinateWithinRectangle(clientX, clientY, (/** @type {?} */ (droppableElement.rect)));
1139 /** @type {?} */
1140 var isDropAllowed = !_this.validateDrop ||
1141 _this.validateDrop({ clientX: clientX, clientY: clientY, target: target });
1142 if (droppableElement.scrollContainerRect) {
1143 return (isWithinElement &&
1144 isDropAllowed &&
1145 isCoordinateWithinRectangle(clientX, clientY, (/** @type {?} */ (droppableElement.scrollContainerRect))));
1146 }
1147 else {
1148 return isWithinElement && isDropAllowed;
1149 }
1150 })));
1151 /** @type {?} */
1152 var overlapsChanged$ = overlaps$.pipe(distinctUntilChanged());
1153 /** @type {?} */
1154 var dragOverActive;
1155 overlapsChanged$
1156 .pipe(filter((/**
1157 * @param {?} overlapsNow
1158 * @return {?}
1159 */
1160 function (overlapsNow) { return overlapsNow; })))
1161 .subscribe((/**
1162 * @return {?}
1163 */
1164 function () {
1165 dragOverActive = true;
1166 addClass(_this.renderer, _this.element, _this.dragOverClass);
1167 _this.zone.run((/**
1168 * @return {?}
1169 */
1170 function () {
1171 _this.dragEnter.next({
1172 dropData: currentDragDropData,
1173 });
1174 }));
1175 }));
1176 overlaps$.pipe(filter((/**
1177 * @param {?} overlapsNow
1178 * @return {?}
1179 */
1180 function (overlapsNow) { return overlapsNow; }))).subscribe((/**
1181 * @return {?}
1182 */
1183 function () {
1184 _this.zone.run((/**
1185 * @return {?}
1186 */
1187 function () {
1188 _this.dragOver.next({
1189 dropData: currentDragDropData,
1190 });
1191 }));
1192 }));
1193 overlapsChanged$
1194 .pipe(pairwise(), filter((/**
1195 * @param {?} __0
1196 * @return {?}
1197 */
1198 function (_a) {
1199 var _b = __read(_a, 2), didOverlap = _b[0], overlapsNow = _b[1];
1200 return didOverlap && !overlapsNow;
1201 })))
1202 .subscribe((/**
1203 * @return {?}
1204 */
1205 function () {
1206 dragOverActive = false;
1207 removeClass(_this.renderer, _this.element, _this.dragOverClass);
1208 _this.zone.run((/**
1209 * @return {?}
1210 */
1211 function () {
1212 _this.dragLeave.next({
1213 dropData: currentDragDropData,
1214 });
1215 }));
1216 }));
1217 drag$.subscribe({
1218 complete: (/**
1219 * @return {?}
1220 */
1221 function () {
1222 deregisterScrollListener();
1223 removeClass(_this.renderer, _this.element, _this.dragActiveClass);
1224 if (dragOverActive) {
1225 removeClass(_this.renderer, _this.element, _this.dragOverClass);
1226 _this.zone.run((/**
1227 * @return {?}
1228 */
1229 function () {
1230 _this.drop.next({
1231 dropData: currentDragDropData,
1232 });
1233 }));
1234 }
1235 }),
1236 });
1237 }));
1238 };
1239 /**
1240 * @return {?}
1241 */
1242 DroppableDirective.prototype.ngOnDestroy = /**
1243 * @return {?}
1244 */
1245 function () {
1246 if (this.currentDragSubscription) {
1247 this.currentDragSubscription.unsubscribe();
1248 }
1249 };
1250 DroppableDirective.decorators = [
1251 { type: Directive, args: [{
1252 selector: '[mwlDroppable]',
1253 },] }
1254 ];
1255 /** @nocollapse */
1256 DroppableDirective.ctorParameters = function () { return [
1257 { type: ElementRef },
1258 { type: DraggableHelper },
1259 { type: NgZone },
1260 { type: Renderer2 },
1261 { type: DraggableScrollContainerDirective, decorators: [{ type: Optional }] }
1262 ]; };
1263 DroppableDirective.propDecorators = {
1264 dragOverClass: [{ type: Input }],
1265 dragActiveClass: [{ type: Input }],
1266 validateDrop: [{ type: Input }],
1267 dragEnter: [{ type: Output }],
1268 dragLeave: [{ type: Output }],
1269 dragOver: [{ type: Output }],
1270 drop: [{ type: Output }]
1271 };
1272 return DroppableDirective;
1273}());
1274
1275/**
1276 * @fileoverview added by tsickle
1277 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
1278 */
1279var DragAndDropModule = /** @class */ (function () {
1280 function DragAndDropModule() {
1281 }
1282 DragAndDropModule.decorators = [
1283 { type: NgModule, args: [{
1284 declarations: [
1285 DraggableDirective,
1286 DroppableDirective,
1287 DraggableScrollContainerDirective,
1288 ],
1289 exports: [
1290 DraggableDirective,
1291 DroppableDirective,
1292 DraggableScrollContainerDirective,
1293 ],
1294 },] }
1295 ];
1296 return DragAndDropModule;
1297}());
1298
1299/**
1300 * @fileoverview added by tsickle
1301 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
1302 */
1303
1304/**
1305 * @fileoverview added by tsickle
1306 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
1307 */
1308
1309export { DragAndDropModule, DraggableHelper as ɵc, DraggableScrollContainerDirective as ɵd, DraggableDirective as ɵb, DroppableDirective as ɵa };
1310
1311//# sourceMappingURL=angular-draggable-droppable.js.map
\No newline at end of file