* Check if a node can be moved to a new position, considering layout constraints. * This is a safer version of moveNode() that validates the move first. * * For complex cases (like maxRow constraints), it simulates the move in a clone first, * then applies the changes only if they meet a
(node: GridStackNode, o: GridStackMoveOpts)
| 841 | * } |
| 842 | */ |
| 843 | public moveNodeCheck(node: GridStackNode, o: GridStackMoveOpts): boolean { |
| 844 | // if (node.locked) return false; |
| 845 | if (!this.changedPosConstrain(node, o)) return false; |
| 846 | o.pack = true; |
| 847 | |
| 848 | // simpler case: move item directly... |
| 849 | if (!this.maxRow) { |
| 850 | return this.moveNode(node, o); |
| 851 | } |
| 852 | |
| 853 | // complex case: create a clone with NO maxRow (will check for out of bounds at the end) |
| 854 | let clonedNode: GridStackNode; |
| 855 | const clone = new GridStackEngine({ |
| 856 | column: this.column, |
| 857 | float: this.float, |
| 858 | nodes: this.nodes.map(n => { |
| 859 | if (n._id === node._id) { |
| 860 | clonedNode = {...n}; |
| 861 | return clonedNode; |
| 862 | } |
| 863 | return {...n}; |
| 864 | }) |
| 865 | }); |
| 866 | if (!clonedNode) return false; |
| 867 | |
| 868 | // check if we're covering 50% collision and could move, while still being under maxRow or at least not making it worse |
| 869 | // (case where widget was somehow added past our max #2449) |
| 870 | const canMove = clone.moveNode(clonedNode, o) && clone.getRow() <= Math.max(this.getRow(), this.maxRow); |
| 871 | // else check if we can force a swap (float=true, or different shapes) on non-resize |
| 872 | if (!canMove && !o.resizing && o.collide) { |
| 873 | const collide = o.collide.el.gridstackNode; // find the source node the clone collided with at 50% |
| 874 | if (this.swap(node, collide)) { // swaps and mark dirty |
| 875 | this._notify(); |
| 876 | return true; |
| 877 | } |
| 878 | } |
| 879 | if (!canMove) return false; |
| 880 | |
| 881 | // if clone was able to move, copy those mods over to us now instead of caller trying to do this all over! |
| 882 | // Note: we can't use the list directly as elements and other parts point to actual node, so copy content |
| 883 | clone.nodes.filter(n => n._dirty).forEach(c => { |
| 884 | const n = this.nodes.find(a => a._id === c._id); |
| 885 | if (!n) return; |
| 886 | Utils.copyPos(n, c); |
| 887 | n._dirty = true; |
| 888 | }); |
| 889 | this._notify(); |
| 890 | return true; |
| 891 | } |
| 892 | |
| 893 | /** return true if can fit in grid height constrain only (always true if no maxRow) */ |
| 894 | public willItFit(node: GridStackNode): boolean { |
no test coverage detected