* Convert an existing gridItem element into a sub-grid with the given (optional) options, else inherit them * from the parent's subGrid options. * @param el gridItem element to convert * @param ops (optional) sub-grid options, else default to node, then parent settings, else defaults * @
(el: GridItemHTMLElement, ops?: GridStackOptions, nodeToAdd?: GridStackNode, saveContent = true)
| 504 | * @returns newly created grid |
| 505 | */ |
| 506 | public makeSubGrid(el: GridItemHTMLElement, ops?: GridStackOptions, nodeToAdd?: GridStackNode, saveContent = true): GridStack { |
| 507 | let node = el.gridstackNode; |
| 508 | if (!node) { |
| 509 | node = this.makeWidget(el).gridstackNode; |
| 510 | } |
| 511 | if (node.subGrid?.el) return node.subGrid; // already done |
| 512 | |
| 513 | // find the template subGrid stored on a parent as fallback... |
| 514 | let subGridTemplate: GridStackOptions; // eslint-disable-next-line @typescript-eslint/no-this-alias |
| 515 | let grid: GridStack = this; |
| 516 | while (grid && !subGridTemplate) { |
| 517 | subGridTemplate = grid.opts?.subGridOpts; |
| 518 | grid = grid.parentGridNode?.grid; |
| 519 | } |
| 520 | //... and set the create options |
| 521 | ops = Utils.cloneDeep({ |
| 522 | // by default sub-grid inherit from us | parent, other than id, children, etc... |
| 523 | ...this.opts, id: undefined, children: undefined, column: 'auto', columnOpts: undefined, layout: 'list', subGridOpts: undefined, |
| 524 | ...(subGridTemplate || {}), |
| 525 | ...(ops || node.subGridOpts || {}) |
| 526 | }); |
| 527 | node.subGridOpts = ops; |
| 528 | |
| 529 | // if column special case it set, remember that flag and set default |
| 530 | let autoColumn: boolean; |
| 531 | if (ops.column === 'auto') { |
| 532 | autoColumn = true; |
| 533 | ops.column = Math.max(node.w || 1, nodeToAdd?.w || 1); |
| 534 | delete ops.columnOpts; // driven by parent |
| 535 | } |
| 536 | |
| 537 | // if we're converting an existing full item, move over the content to be the first sub item in the new grid |
| 538 | let content = node.el.querySelector('.grid-stack-item-content') as HTMLElement; |
| 539 | let newItem: HTMLElement; |
| 540 | let newItemOpt: GridStackNode; |
| 541 | if (saveContent) { |
| 542 | this._removeDD(node.el); // remove D&D since it's set on content div |
| 543 | newItemOpt = { ...node, x: 0, y: 0 }; |
| 544 | Utils.removeInternalForSave(newItemOpt); |
| 545 | delete newItemOpt.subGridOpts; |
| 546 | if (node.content) { |
| 547 | newItemOpt.content = node.content; |
| 548 | delete node.content; |
| 549 | } |
| 550 | if (GridStack.addRemoveCB) { |
| 551 | newItem = GridStack.addRemoveCB(this.el, newItemOpt, true, false); |
| 552 | } else { |
| 553 | newItem = Utils.createDiv(['grid-stack-item']); |
| 554 | newItem.appendChild(content); |
| 555 | content = Utils.createDiv(['grid-stack-item-content'], node.el); |
| 556 | } |
| 557 | this.prepareDragDrop(node.el); // ... and restore original D&D |
| 558 | } |
| 559 | |
| 560 | // if we're adding an additional item, make the container large enough to have them both |
| 561 | if (nodeToAdd) { |
| 562 | const w = autoColumn ? ops.column : node.w; |
| 563 | const h = node.h + nodeToAdd.h; |
no test coverage detected