@@ -54,7 +54,7 @@ export class GridStackEngine {
54
54
this . onChange = opts . onChange ;
55
55
}
56
56
57
- public batchUpdate ( flag = true ) : GridStackEngine {
57
+ public batchUpdate ( flag = true , doPack = true ) : GridStackEngine {
58
58
if ( ! ! this . batchMode === flag ) return this ;
59
59
this . batchMode = flag ;
60
60
if ( flag ) {
@@ -64,7 +64,8 @@ export class GridStackEngine {
64
64
} else {
65
65
this . _float = this . _prevFloat ;
66
66
delete this . _prevFloat ;
67
- this . _packNodes ( ) . _notify ( ) ;
67
+ if ( doPack ) this . _packNodes ( ) ;
68
+ this . _notify ( ) ;
68
69
}
69
70
return this ;
70
71
}
@@ -258,12 +259,14 @@ export class GridStackEngine {
258
259
return ! this . collide ( nn ) ;
259
260
}
260
261
261
- /** re-layout grid items to reclaim any empty space - optionally keeping the sort order exactly the same (list mode) vs truly finding an empty spaces */
262
- public compact ( layout : CompactOptions = 'compact' , sortBefore = true ) : GridStackEngine {
262
+ /** re-layout grid items to reclaim any empty space - optionally keeping the sort order exactly the same (' list' mode) vs truly finding an empty spaces */
263
+ public compact ( layout : CompactOptions = 'compact' , doSort = true ) : GridStackEngine {
263
264
if ( this . nodes . length === 0 ) return this ;
264
- this . batchUpdate ( )
265
- if ( sortBefore ) this . sortNodes ( ) ;
266
- this . _inColumnResize = true ; // faster addNode()
265
+ if ( doSort ) this . sortNodes ( ) ;
266
+ const wasBatch = this . batchMode ;
267
+ if ( ! wasBatch ) this . batchUpdate ( ) ;
268
+ const wasColumnResize = this . _inColumnResize ;
269
+ if ( ! wasColumnResize ) this . _inColumnResize = true ; // faster addNode()
267
270
let copyNodes = this . nodes ;
268
271
this . nodes = [ ] ; // pretend we have no nodes to conflict layout to start with...
269
272
copyNodes . forEach ( ( n , index , list ) => {
@@ -274,8 +277,9 @@ export class GridStackEngine {
274
277
}
275
278
this . addNode ( n , false , after ) ; // 'false' for add event trigger
276
279
} ) ;
277
- delete this . _inColumnResize ;
278
- return this . batchUpdate ( false ) ;
280
+ if ( ! wasColumnResize ) delete this . _inColumnResize ;
281
+ if ( ! wasBatch ) this . batchUpdate ( false ) ;
282
+ return this ;
279
283
}
280
284
281
285
/** enable/disable floating widgets (default: `false`) See [example](http://gridstackjs.com/demo/float.html) */
@@ -518,14 +522,16 @@ export class GridStackEngine {
518
522
delete node . _temporaryRemoved ;
519
523
delete node . _removeDOM ;
520
524
525
+ let skipCollision : boolean ;
521
526
if ( node . autoPosition && this . findEmptyPosition ( node , this . nodes , this . column , after ) ) {
522
527
delete node . autoPosition ; // found our slot
528
+ skipCollision = true ;
523
529
}
524
530
525
531
this . nodes . push ( node ) ;
526
532
if ( triggerAddEvent ) { this . addedNodes . push ( node ) ; }
527
533
528
- this . _fixCollisions ( node ) ;
534
+ if ( ! skipCollision ) this . _fixCollisions ( node ) ;
529
535
if ( ! this . batchMode ) { this . _packNodes ( ) . _notify ( ) ; }
530
536
return node ;
531
537
}
@@ -792,23 +798,21 @@ export class GridStackEngine {
792
798
* @param layout specify the type of re-layout that will happen (position, size, etc...).
793
799
* Note: items will never be outside of the current column boundaries. default (moveScale). Ignored for 1 column
794
800
*/
795
- public updateNodeWidths ( prevColumn : number , column : number , nodes : GridStackNode [ ] , layout : ColumnOptions = 'moveScale' ) : GridStackEngine {
801
+ public columnChanged ( prevColumn : number , column : number , nodes : GridStackNode [ ] , layout : ColumnOptions = 'moveScale' ) : GridStackEngine {
796
802
if ( ! this . nodes . length || ! column || prevColumn === column ) return this ;
797
803
798
804
// simpler shortcuts layouts
799
805
const doCompact = layout === 'compact' || layout === 'list' ;
800
806
if ( doCompact ) {
801
807
this . sortNodes ( 1 , prevColumn ) ; // sort with original layout once and only once (new column will affect order otherwise)
802
- return this . compact ( layout , false ) ;
803
808
}
804
-
805
- // cache the current layout in case they want to go back (like 12 -> 1 -> 12) as it requires original data
806
- this . cacheLayout ( this . nodes , prevColumn ) ;
809
+
810
+ // cache the current layout in case they want to go back (like 12 -> 1 -> 12) as it requires original data IFF we're sizing down (see below)
811
+ if ( column < prevColumn ) this . cacheLayout ( this . nodes , prevColumn ) ;
807
812
this . batchUpdate ( ) ; // do this EARLY as it will call saveInitial() so we can detect where we started for _dirty and collision
808
813
let newNodes : GridStackNode [ ] = [ ] ;
809
-
810
-
811
- // if we're going to 1 column and using DOM order rather than default sorting, then generate that layout
814
+
815
+ // if we're going to 1 column and using DOM order (item passed in) rather than default sorting, then generate that layout
812
816
let domOrder = false ;
813
817
if ( column === 1 && nodes ?. length ) {
814
818
domOrder = true ;
@@ -822,14 +826,13 @@ export class GridStackEngine {
822
826
newNodes = nodes ;
823
827
nodes = [ ] ;
824
828
} else {
825
- nodes = Utils . sort ( this . nodes , - 1 , prevColumn ) ; // current column reverse sorting so we can insert last to front (limit collision)
829
+ nodes = doCompact ? this . nodes : Utils . sort ( this . nodes , - 1 , prevColumn ) ; // current column reverse sorting so we can insert last to front (limit collision)
826
830
}
827
831
828
832
// see if we have cached previous layout IFF we are going up in size (restore) otherwise always
829
833
// generate next size down from where we are (looks more natural as you gradually size down).
830
- let cacheNodes : GridStackNode [ ] = [ ] ;
831
- if ( column > prevColumn ) {
832
- cacheNodes = this . _layouts [ column ] || [ ] ;
834
+ if ( column > prevColumn && this . _layouts ) {
835
+ const cacheNodes = this . _layouts [ column ] || [ ] ;
833
836
// ...if not, start with the largest layout (if not already there) as down-scaling is more accurate
834
837
// by pretending we came from that larger column by assigning those values as starting point
835
838
let lastIndex = this . _layouts . length - 1 ;
@@ -839,59 +842,72 @@ export class GridStackEngine {
839
842
let n = nodes . find ( n => n . _id === cacheNode . _id ) ;
840
843
if ( n ) {
841
844
// still current, use cache info positions
842
- n . x = cacheNode . x ;
843
- n . y = cacheNode . y ;
845
+ if ( ! doCompact ) {
846
+ n . x = cacheNode . x ;
847
+ n . y = cacheNode . y ;
848
+ }
844
849
n . w = cacheNode . w ;
845
850
}
846
851
} ) ;
847
852
}
848
- }
849
853
850
- // if we found cache re-use those nodes that are still current
851
- cacheNodes . forEach ( cacheNode => {
852
- let j = nodes . findIndex ( n => n . _id === cacheNode . _id ) ;
853
- if ( j !== - 1 ) {
854
- // still current, use cache info positions
855
- if ( cacheNode . autoPosition || isNaN ( cacheNode . x ) || isNaN ( cacheNode . y ) ) {
856
- this . findEmptyPosition ( cacheNode , newNodes ) ;
854
+ // if we found cache re-use those nodes that are still current
855
+ cacheNodes . forEach ( cacheNode => {
856
+ let j = nodes . findIndex ( n => n . _id === cacheNode . _id ) ;
857
+ if ( j !== - 1 ) {
858
+ // still current, use cache info positions
859
+ if ( doCompact ) {
860
+ nodes [ j ] . w = cacheNode . w ; // only w is used, and don't trim the list
861
+ return ;
862
+ }
863
+ if ( cacheNode . autoPosition || isNaN ( cacheNode . x ) || isNaN ( cacheNode . y ) ) {
864
+ this . findEmptyPosition ( cacheNode , newNodes ) ;
865
+ }
866
+ if ( ! cacheNode . autoPosition ) {
867
+ nodes [ j ] . x = cacheNode . x ;
868
+ nodes [ j ] . y = cacheNode . y ;
869
+ nodes [ j ] . w = cacheNode . w ;
870
+ newNodes . push ( nodes [ j ] ) ;
871
+ }
872
+ nodes . splice ( j , 1 ) ;
857
873
}
858
- if ( ! cacheNode . autoPosition ) {
859
- nodes [ j ] . x = cacheNode . x ;
860
- nodes [ j ] . y = cacheNode . y ;
861
- nodes [ j ] . w = cacheNode . w ;
862
- newNodes . push ( nodes [ j ] ) ;
874
+ } ) ;
875
+ }
876
+
877
+ // much simpler layout that just compacts
878
+ if ( doCompact ) {
879
+ this . compact ( layout , false ) ;
880
+ } else {
881
+ // ...and add any extra non-cached ones
882
+ if ( nodes . length ) {
883
+ if ( typeof layout === 'function' ) {
884
+ layout ( column , prevColumn , newNodes , nodes ) ;
885
+ } else if ( ! domOrder ) {
886
+ let ratio = ( doCompact || layout === 'none' ) ? 1 : column / prevColumn ;
887
+ let move = ( layout === 'move' || layout === 'moveScale' ) ;
888
+ let scale = ( layout === 'scale' || layout === 'moveScale' ) ;
889
+ nodes . forEach ( node => {
890
+ // NOTE: x + w could be outside of the grid, but addNode() below will handle that
891
+ node . x = ( column === 1 ? 0 : ( move ? Math . round ( node . x * ratio ) : Math . min ( node . x , column - 1 ) ) ) ;
892
+ node . w = ( ( column === 1 || prevColumn === 1 ) ? 1 : scale ? ( Math . round ( node . w * ratio ) || 1 ) : ( Math . min ( node . w , column ) ) ) ;
893
+ newNodes . push ( node ) ;
894
+ } ) ;
895
+ nodes = [ ] ;
863
896
}
864
- nodes . splice ( j , 1 ) ;
865
897
}
866
- } ) ;
867
- // ...and add any extra non-cached ones
868
- if ( nodes . length ) {
869
- if ( typeof layout === 'function' ) {
870
- layout ( column , prevColumn , newNodes , nodes ) ;
871
- } else if ( ! domOrder ) {
872
- let ratio = column / prevColumn ;
873
- let move = ( layout === 'move' || layout === 'moveScale' ) ;
874
- let scale = ( layout === 'scale' || layout === 'moveScale' ) ;
875
- nodes . forEach ( node => {
876
- // NOTE: x + w could be outside of the grid, but addNode() below will handle that
877
- node . x = ( column === 1 ? 0 : ( move ? Math . round ( node . x * ratio ) : Math . min ( node . x , column - 1 ) ) ) ;
878
- node . w = ( ( column === 1 || prevColumn === 1 ) ? 1 :
879
- scale ? ( Math . round ( node . w * ratio ) || 1 ) : ( Math . min ( node . w , column ) ) ) ;
880
- newNodes . push ( node ) ;
881
- } ) ;
882
- nodes = [ ] ;
883
- }
884
- }
885
898
886
- // finally re-layout them in reverse order (to get correct placement)
887
- if ( ! domOrder ) newNodes = Utils . sort ( newNodes , - 1 , column ) ;
888
- this . _inColumnResize = true ; // prevent cache update
889
- this . nodes = [ ] ; // pretend we have no nodes to start with (add() will use same structures) to simplify layout
890
- newNodes . forEach ( node => {
891
- this . addNode ( node , false ) ; // 'false' for add event trigger
892
- delete node . _orig ; // make sure the commit doesn't try to restore things back to original
893
- } ) ;
894
- this . batchUpdate ( false ) ;
899
+ // finally re-layout them in reverse order (to get correct placement)
900
+ if ( ! domOrder ) newNodes = Utils . sort ( newNodes , - 1 , column ) ;
901
+ this . _inColumnResize = true ; // prevent cache update
902
+ this . nodes = [ ] ; // pretend we have no nodes to start with (add() will use same structures) to simplify layout
903
+ newNodes . forEach ( node => {
904
+ this . addNode ( node , false ) ; // 'false' for add event trigger
905
+ delete node . _orig ; // make sure the commit doesn't try to restore things back to original
906
+ } ) ;
907
+ }
908
+
909
+ this . nodes . forEach ( n => delete n . _orig ) ; // clear _orig before batch=false so it doesn't handle float=true restore
910
+ this . batchUpdate ( false , ! doCompact ) ;
895
911
delete this . _inColumnResize ;
896
912
return this ;
897
913
}
0 commit comments