Skip to content

Commit a64716f

Browse files
authored
Merge pull request #1425 from adumesny/develop
custom column re-layout callback
2 parents c4b57f9 + a51ae80 commit a64716f

File tree

6 files changed

+48
-23
lines changed

6 files changed

+48
-23
lines changed

demo/column.html

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ <h1>column() grid demo</h1>
1616
<div><span>Number of Columns:</span> <span id="column-text">12</span></div>
1717
<div>
1818
<label>Choose re-layout:</label>
19-
<select onchange="layout = this.value">
19+
<select onchange="setLayout(this.value)">
2020
<option value="moveScale">move + scale</option>
2121
<option value="move">move</option>
2222
<option value="scale">scale</option>
2323
<option value="none">none</option>
24+
<option value="custom">custom</option>
2425
</select>
2526
</div>
2627
<div>
@@ -91,6 +92,17 @@ <h1>column() grid demo</h1>
9192
grid.column(1, layout);
9293
text.innerHTML = dom ? '1 DOM' : '1';
9394
}
95+
// dummy test method that moves items to the right each new layout... grid engine will validate those values (can't be neg or out of bounds) anyway...
96+
function columnLayout(column, oldColumn, nodes, oldNodes) {
97+
oldNodes.forEach(n => {
98+
n.x = n.x + 1;
99+
nodes.push(n);
100+
});
101+
oldNodes.length = 0;
102+
}
103+
function setLayout(name) {
104+
layout = name === 'custom' ? this.columnLayout : name;
105+
}
94106

95107
</script>
96108
</body>

doc/CHANGES.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ Also fixed JQ draggable warning if not initialized first [858](https://github.co
4646
- add `addWidget(opt)` now handles just passing a `GridStackWidget` which creates the default divs, simplifying your code. Old API still supported.
4747
- add `save(saveContent = true)` now lets you optionally save the HTML content in the node property, with load() restoring it [1418](https://github.com/gridstack/gridstack.js/issues/1418)
4848
- add `GridStackWidget.content` now lets you add any HTML content when calling `load()/save()` or `addWidget()` [1418](https://github.com/gridstack/gridstack.js/issues/1418)
49-
- add `LayoutOptions` to `column()` for multiple re-layout options, including 'none' that will preserve the x and width, until out of bound/overlap [1338](https://github.com/gridstack/gridstack.js/issues/1338)
49+
- add `ColumnOptions` to `column(n, options)` for multiple re-layout options, including 'none' that will preserve the x and width, until out of bound/overlap [1338](https://github.com/gridstack/gridstack.js/issues/1338)
50+
including a custom function for you to create the new layout [1332](https://github.com/gridstack/gridstack.js/issues/1332)
5051

5152
## 2.0.2 (2020-10-05)
5253

doc/README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ gridstack.js API
2727
- [cellHeight(val: number, update = true)](#cellheightval-number-update--true)
2828
- [cellWidth()](#cellwidth)
2929
- [commit()](#commit)
30-
- [column(column: number, layout: LayoutOptions = 'moveScale')](#columncolumn-number-layout-layoutoptions--movescale)
30+
- [column(column: number, layout: ColumnOptions = 'moveScale')](#columncolumn-number-layout-columnoptions--movescale)
3131
- [destroy([removeDOM])](#destroyremovedom)
3232
- [disable()](#disable)
3333
- [enable()](#enable)
@@ -298,7 +298,7 @@ Gets current cell width (grid width / # of columns).
298298

299299
Ends batch updates. Updates DOM nodes. You must call it after `batchUpdate()`.
300300

301-
### column(column: number, layout: LayoutOptions = 'moveScale')
301+
### column(column: number, layout: ColumnOptions = 'moveScale')
302302

303303
set/get the number of columns in the grid. Will update existing widgets to conform to new number of columns,
304304
as well as cache the original layout so you can revert back to previous positions without loss.
@@ -308,7 +308,9 @@ else you will need to generate correct CSS (see https://github.com/gridstack/gri
308308
- `column` - Integer > 0 (default 12), if missing it will return the current count instead.
309309
- `layout` - specify the type of re-layout that will happen (position, size, etc...).
310310
Note: items will never be outside of the current column boundaries. default ('moveScale'). Ignored for 1 column.
311-
Possible values: 'moveScale' | 'move' | 'scale' | 'none'
311+
Possible values: 'moveScale' | 'move' | 'scale' | 'none' | (column: number, oldColumn: number, nodes: GridStackNode[], oldNodes: GridStackNode[]) => void.
312+
A custom function option takes new/old column count, and array of new/old positions.
313+
Note: new list may be partially already filled if we have a partial cache of the layout at that size (items were added later). If complete cache is present this won't get called at all.
312314

313315
### destroy([removeDOM])
314316

src/gridstack-engine.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import { Utils, obsolete } from './utils';
10-
import { GridStackNode, LayoutOptions } from './types';
10+
import { GridStackNode, ColumnOptions } from './types';
1111

1212
export type onChangeCB = (nodes: GridStackNode[], removeDOM?: boolean) => void;
1313

@@ -537,7 +537,7 @@ export class GridStackEngine {
537537
* @param layout specify the type of re-layout that will happen (position, size, etc...).
538538
* Note: items will never be outside of the current column boundaries. default (moveScale). Ignored for 1 column
539539
*/
540-
public updateNodeWidths(oldColumn: number, column: number, nodes: GridStackNode[], layout: LayoutOptions = 'moveScale'): GridStackEngine {
540+
public updateNodeWidths(oldColumn: number, column: number, nodes: GridStackNode[], layout: ColumnOptions = 'moveScale'): GridStackEngine {
541541
if (!this.nodes.length || oldColumn === column) { return this }
542542

543543
// cache the current layout in case they want to go back (like 12 -> 1 -> 12) as it requires original data
@@ -584,27 +584,33 @@ export class GridStackEngine {
584584
// if we found cache re-use those nodes that are still current
585585
let newNodes: GridStackNode[] = [];
586586
cacheNodes.forEach(cacheNode => {
587-
let j = nodes.findIndex(n => n && n._id === cacheNode._id);
587+
let j = nodes.findIndex(n => n._id === cacheNode._id);
588588
if (j !== -1) {
589589
// still current, use cache info positions
590590
nodes[j].x = cacheNode.x;
591591
nodes[j].y = cacheNode.y;
592592
nodes[j].width = cacheNode.width;
593593
newNodes.push(nodes[j]);
594-
nodes[j] = null; // erase it so we know what's left
594+
nodes.splice(j, 1);
595595
}
596596
});
597597
// ...and add any extra non-cached ones
598-
let ratio = column / oldColumn;
599-
let move = layout === 'move' || layout === 'moveScale';
600-
let scale = layout === 'scale' || layout === 'moveScale';
601-
nodes.forEach(node => {
602-
if (!node) return this;
603-
node.x = (column === 1 ? 0 : (move ? Math.round(node.x * ratio) : Math.min(node.x, column - 1)));
604-
node.width = ((column === 1 || oldColumn === 1) ? 1 :
605-
scale ? (Math.round(node.width * ratio) || 1) : (Math.min(node.width, column)));
606-
newNodes.push(node);
607-
});
598+
if (nodes.length) {
599+
if (typeof layout === 'function') {
600+
layout(column, oldColumn, newNodes, nodes);
601+
} else {
602+
let ratio = column / oldColumn;
603+
let move = (layout === 'move' || layout === 'moveScale');
604+
let scale = (layout === 'scale' || layout === 'moveScale');
605+
nodes.forEach(node => {
606+
node.x = (column === 1 ? 0 : (move ? Math.round(node.x * ratio) : Math.min(node.x, column - 1)));
607+
node.width = ((column === 1 || oldColumn === 1) ? 1 :
608+
scale ? (Math.round(node.width * ratio) || 1) : (Math.min(node.width, column)));
609+
newNodes.push(node);
610+
});
611+
nodes = [];
612+
}
613+
}
608614

609615
// finally re-layout them in reverse order (to get correct placement)
610616
newNodes = Utils.sort(newNodes, -1, column);

src/gridstack.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import { GridStackEngine } from './gridstack-engine';
1010
import { obsoleteOpts, obsoleteOptsDel, obsoleteAttr, obsolete, Utils } from './utils';
11-
import { GridItemHTMLElement, GridStackWidget, GridStackNode, GridStackOptions, numberOrString, LayoutOptions } from './types';
11+
import { GridItemHTMLElement, GridStackWidget, GridStackNode, GridStackOptions, numberOrString, ColumnOptions } from './types';
1212
import { GridStackDD } from './gridstack-dd';
1313

1414
// export all dependent file as well to make it easier for users to just import the main file
@@ -516,7 +516,7 @@ export class GridStack {
516516
* @param layout specify the type of re-layout that will happen (position, size, etc...).
517517
* Note: items will never be outside of the current column boundaries. default (moveScale). Ignored for 1 column
518518
*/
519-
public column(column: number, layout: LayoutOptions = 'moveScale'): GridStack {
519+
public column(column: number, layout: ColumnOptions = 'moveScale'): GridStack {
520520
if (this.opts.column === column) { return this; }
521521
let oldColumn = this.opts.column;
522522

src/types.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ import { GridStack } from './gridstack';
1010
import { GridStackDD } from './gridstack-dd';
1111

1212

13-
/** different layout options when changing # of columns and other re-layouts */
14-
export type LayoutOptions = 'moveScale' | 'move' | 'scale' | 'none';
13+
/** different layout options when changing # of columns,
14+
* including a custom function that takes new/old column count, and array of new/old positions
15+
* Note: new list may be partially already filled if we have a cache of the layout at that size and new items were added later.
16+
*/
17+
export type ColumnOptions = 'moveScale' | 'move' | 'scale' | 'none' |
18+
((column: number, oldColumn: number, nodes: GridStackNode[], oldNodes: GridStackNode[]) => void);
1519

1620
export type numberOrString = number | string;
1721
export interface GridItemHTMLElement extends HTMLElement {

0 commit comments

Comments
 (0)