| 32 | // let count = 0; // TEST |
| 33 | |
| 34 | export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt<DDDragOpt> { |
| 35 | public helper: HTMLElement; // used by GridStackDDNative |
| 36 | |
| 37 | /** @internal */ |
| 38 | protected mouseDownEvent: MouseEvent; |
| 39 | /** @internal */ |
| 40 | protected dragOffset: DragOffset; |
| 41 | /** @internal */ |
| 42 | protected dragElementOriginStyle: Array<string>; |
| 43 | /** @internal */ |
| 44 | protected dragEls: HTMLElement[]; |
| 45 | /** @internal true while we are dragging an item around */ |
| 46 | public dragging: boolean; |
| 47 | /** @internal last drag event */ |
| 48 | public lastDrag: DragEvent; |
| 49 | /** @internal */ |
| 50 | protected parentOriginStylePosition: string; |
| 51 | /** @internal */ |
| 52 | protected helperContainment: HTMLElement; |
| 53 | /** @internal properties we change during dragging, and restore back */ |
| 54 | protected static originStyleProp = ['width', 'height', 'transform', 'transform-origin', 'transition', 'pointerEvents', 'position', 'left', 'right', 'top', 'minWidth', 'willChange']; |
| 55 | /** @internal pause before we call the actual drag hit collision code */ |
| 56 | protected dragTimeout: number; |
| 57 | /** @internal */ |
| 58 | protected dragTransform: DragTransform = { |
| 59 | xScale: 1, |
| 60 | yScale: 1, |
| 61 | xOffset: 0, |
| 62 | yOffset: 0 |
| 63 | }; |
| 64 | /** @internal auto-scroll animation variables */ |
| 65 | protected _autoScrollAnimId?: number; |
| 66 | protected _autoScrollContainer?: HTMLElement; |
| 67 | protected _autoScrollMaxSpeed?: number; |
| 68 | |
| 69 | constructor(public el: GridItemHTMLElement, public option: DDDragOpt = {}) { |
| 70 | super(); |
| 71 | |
| 72 | // get the element that is actually supposed to be dragged by |
| 73 | const handleName = option?.handle?.substring(1); |
| 74 | const n = el.gridstackNode; |
| 75 | this.dragEls = !handleName || el.classList.contains(handleName) ? [el] : (n?.subGrid ? [el.querySelector(option.handle) || el] : this.getAllHandles()); |
| 76 | if (this.dragEls.length === 0) { |
| 77 | this.dragEls = [el]; |
| 78 | } |
| 79 | // create var event binding so we can easily remove and still look like TS methods (unlike anonymous functions) |
| 80 | this._mouseDown = this._mouseDown.bind(this); |
| 81 | this._mouseMove = this._mouseMove.bind(this); |
| 82 | this._mouseUp = this._mouseUp.bind(this); |
| 83 | this._keyEvent = this._keyEvent.bind(this); |
| 84 | this.enable(); |
| 85 | } |
| 86 | |
| 87 | /** return all handles omitting other nested `.grid-stack-item` children (in case node.subGrid isn't set for some reason) */ |
| 88 | protected getAllHandles(): HTMLElement[] { |
| 89 | return Array.from(this.el.querySelectorAll(this.option.handle)).filter((node): node is HTMLElement => { |
| 90 | if (!(node instanceof HTMLElement)) return false; |
| 91 | const owner = node.closest('.grid-stack-item'); |
nothing calls this directly
no test coverage detected