Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c543b08

Browse files
author
Alain Dumesny
authored
Merge pull request gridstack#1126 from adumesny/develop
Custom Responsive Sort Order
2 parents 639d58a + 77df15c commit c543b08

File tree

5 files changed

+162
-21
lines changed

5 files changed

+162
-21
lines changed

demo/column.html

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ <h1>setColumn() grid demo</h1>
2222
<div>
2323
<a class="btn btn-primary" id="add-widget" href="#">Add Widget</a>
2424
<a class="btn btn-primary" id="1column" href="#">1 Column</a>
25+
<a class="btn btn-primary" id="1columnDOM" href="#">1 Column DOM</a>
2526
<a class="btn btn-primary" id="2column" href="#">2 Column</a>
2627
<a class="btn btn-primary" id="3column" href="#">3 Column</a>
2728
<a class="btn btn-primary" id="4column" href="#">4 Column</a>
@@ -54,15 +55,15 @@ <h1>setColumn() grid demo</h1>
5455
var items = [
5556
{x: 0, y: 0, width: 2, height: 2},
5657
{x: 2, y: 0, width: 2, height: 1},
57-
{x: 5, y: 0, width: 1, height: 1},
58+
{x: 5, y: 1, width: 1, height: 1},
59+
{x: 5, y: 0, width: 2, height: 1},
5860
{text: ' auto'}, // autoPosition testing
59-
{x: 1, y: 3, width: 4, height: 1},
6061
{x: 5, y: 3, width: 2, height: 1},
6162
{x: 0, y: 4, width: 12, height: 1}
6263
];
6364
var count = 0;
6465
grid.batchUpdate();
65-
for (count=0; count<3;) {
66+
for (count=0; count<4;) {
6667
var n = items[count];
6768
grid.addWidget($('<div><div class="grid-stack-item-content">' + count++ + (n.text ? n.text : '') + '</div></div>'), n);
6869
};
@@ -78,7 +79,8 @@ <h1>setColumn() grid demo</h1>
7879
grid.addWidget($('<div><div class="grid-stack-item-content">' + count++ + (n.text ? n.text : '') + '</div></div>'), n);
7980
});
8081

81-
$('#1column').click(function() { grid.setColumn(1); $text.text(1);});
82+
$('#1column').click(function() { delete grid.opts.oneColumnModeDomSort; grid.setColumn(1); $text.text(1);});
83+
$('#1columnDOM').click(function() { grid.opts.oneColumnModeDomSort = true; grid.setColumn(1); $text.text('1 DOM');});
8284
$('#2column').click(function() { grid.setColumn(2); $text.text(2);});
8385
$('#3column').click(function() { grid.setColumn(3); $text.text(3);});
8486
$('#4column').click(function() { grid.setColumn(4); $text.text(4);});

doc/CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Change log
2929

3030
## v0.6.1-dev (upcoming changes)
3131

32+
- add `oneColumnModeDomSort` true|false to let you specify a custom layout (use dom order instead of x,y) for oneColumnMode `setColumn(1)` [#713](https://github.com/gridstack/gridstack.js/issues/713)
3233
- fix oneColumnMode to only restore if we auto went to it as window sizes up [#1125](https://github.com/gridstack/gridstack.js/pull/1125)
3334

3435
## v0.6.1 (2020-02-02)

spec/gridstack-spec.js

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ describe('gridstack', function() {
1515
' </div>' +
1616
' </div>' +
1717
'</div>';
18+
// empty grid
19+
var gridstackEmptyHTML =
20+
'<div style="width: 992px; height: 800px" id="gs-cont">' +
21+
' <div class="grid-stack">' +
22+
' </div>' +
23+
'</div>';
1824
// generic widget with no param
1925
var widgetHTML = '<div class="grid-stack-item" id="item3"><div class="grid-stack-item-content"> hello </div></div>';
2026

@@ -441,6 +447,104 @@ describe('gridstack', function() {
441447
});
442448
});
443449

450+
describe('oneColumnModeDomSort', function() {
451+
beforeEach(function() {
452+
document.body.insertAdjacentHTML('afterbegin', gridstackEmptyHTML);
453+
});
454+
afterEach(function() {
455+
document.body.removeChild(document.getElementById('gs-cont'));
456+
});
457+
it('should support default going to 1 column', function() {
458+
var options = {
459+
column: 12,
460+
float: true
461+
};
462+
$('.grid-stack').gridstack(options);
463+
var grid = $('.grid-stack').data('gridstack');
464+
var el1 = grid.addWidget(widgetHTML, {width:1, height:1});
465+
var el2 = grid.addWidget(widgetHTML, {x:2, y:0, width:2, height:1});
466+
var el3 = grid.addWidget(widgetHTML, {x:1, y:0, width:1, height:2});
467+
468+
// items are item1[1x1], item3[1x1], item2[2x1]
469+
expect(parseInt(el1.attr('data-gs-x'))).toBe(0);
470+
expect(parseInt(el1.attr('data-gs-y'))).toBe(0);
471+
expect(parseInt(el1.attr('data-gs-width'))).toBe(1);
472+
expect(parseInt(el1.attr('data-gs-height'))).toBe(1);
473+
474+
expect(parseInt(el3.attr('data-gs-x'))).toBe(1);
475+
expect(parseInt(el3.attr('data-gs-y'))).toBe(0);
476+
expect(parseInt(el3.attr('data-gs-width'))).toBe(1);
477+
expect(parseInt(el3.attr('data-gs-height'))).toBe(2);
478+
479+
expect(parseInt(el2.attr('data-gs-x'))).toBe(2);
480+
expect(parseInt(el2.attr('data-gs-y'))).toBe(0);
481+
expect(parseInt(el2.attr('data-gs-width'))).toBe(2);
482+
expect(parseInt(el2.attr('data-gs-height'))).toBe(1);
483+
484+
// items are item1[1x1], item3[1x2], item2[1x1] in 1 column
485+
grid.setColumn(1);
486+
expect(parseInt(el1.attr('data-gs-x'))).toBe(0);
487+
expect(parseInt(el1.attr('data-gs-y'))).toBe(0);
488+
expect(parseInt(el1.attr('data-gs-width'))).toBe(1);
489+
expect(parseInt(el1.attr('data-gs-height'))).toBe(1);
490+
491+
expect(parseInt(el3.attr('data-gs-x'))).toBe(0);
492+
expect(parseInt(el3.attr('data-gs-y'))).toBe(1);
493+
expect(parseInt(el3.attr('data-gs-width'))).toBe(1);
494+
expect(parseInt(el3.attr('data-gs-height'))).toBe(2);
495+
496+
expect(parseInt(el2.attr('data-gs-x'))).toBe(0);
497+
expect(parseInt(el2.attr('data-gs-y'))).toBe(3);
498+
expect(parseInt(el2.attr('data-gs-width'))).toBe(1);
499+
expect(parseInt(el2.attr('data-gs-height'))).toBe(1);
500+
});
501+
it('should support oneColumnModeDomSort ON going to 1 column', function() {
502+
var options = {
503+
column: 12,
504+
oneColumnModeDomSort: true,
505+
float: true
506+
};
507+
$('.grid-stack').gridstack(options);
508+
var grid = $('.grid-stack').data('gridstack');
509+
var el1 = grid.addWidget(widgetHTML, {width:1, height:1});
510+
var el2 = grid.addWidget(widgetHTML, {x:2, y:0, width:2, height:1});
511+
var el3 = grid.addWidget(widgetHTML, {x:1, y:0, width:1, height:2});
512+
513+
// items are item1[1x1], item3[1x1], item2[2x1]
514+
expect(parseInt(el1.attr('data-gs-x'))).toBe(0);
515+
expect(parseInt(el1.attr('data-gs-y'))).toBe(0);
516+
expect(parseInt(el1.attr('data-gs-width'))).toBe(1);
517+
expect(parseInt(el1.attr('data-gs-height'))).toBe(1);
518+
519+
expect(parseInt(el3.attr('data-gs-x'))).toBe(1);
520+
expect(parseInt(el3.attr('data-gs-y'))).toBe(0);
521+
expect(parseInt(el3.attr('data-gs-width'))).toBe(1);
522+
expect(parseInt(el3.attr('data-gs-height'))).toBe(2);
523+
524+
expect(parseInt(el2.attr('data-gs-x'))).toBe(2);
525+
expect(parseInt(el2.attr('data-gs-y'))).toBe(0);
526+
expect(parseInt(el2.attr('data-gs-width'))).toBe(2);
527+
expect(parseInt(el2.attr('data-gs-height'))).toBe(1);
528+
529+
// items are item1[1x1], item2[1x1], item3[1x2] in 1 column dom ordered
530+
grid.setColumn(1);
531+
expect(parseInt(el1.attr('data-gs-x'))).toBe(0);
532+
expect(parseInt(el1.attr('data-gs-y'))).toBe(0);
533+
expect(parseInt(el1.attr('data-gs-width'))).toBe(1);
534+
expect(parseInt(el1.attr('data-gs-height'))).toBe(1);
535+
536+
expect(parseInt(el2.attr('data-gs-x'))).toBe(0);
537+
expect(parseInt(el2.attr('data-gs-y'))).toBe(1);
538+
expect(parseInt(el2.attr('data-gs-width'))).toBe(1);
539+
expect(parseInt(el2.attr('data-gs-height'))).toBe(1);
540+
541+
expect(parseInt(el3.attr('data-gs-x'))).toBe(0);
542+
expect(parseInt(el3.attr('data-gs-y'))).toBe(2);
543+
expect(parseInt(el3.attr('data-gs-width'))).toBe(1);
544+
expect(parseInt(el3.attr('data-gs-height'))).toBe(2);
545+
});
546+
});
547+
444548
describe('grid.minWidth', function() {
445549
beforeEach(function() {
446550
document.body.insertAdjacentHTML('afterbegin', gridstackHTML);

src/gridstack.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,12 @@ interface GridstackOptions {
496496
*/
497497
oneColumnModeClass ? : string;
498498

499+
/**
500+
* set to true if you want oneColumnMode to use the DOM order and ignore x,y from normal multi column
501+
* layouts during sorting. This enables you to have custom 1 column layout that differ from the rest. (default?: false)
502+
*/
503+
oneColumnModeDomSort?: boolean;
504+
499505
/**
500506
* class for placeholder (default?: 'grid-stack-placeholder')
501507
*/

src/gridstack.js

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,16 @@
5656
return !(a.x + a.width <= b.x || b.x + b.width <= a.x || a.y + a.height <= b.y || b.y + b.height <= a.y);
5757
},
5858

59-
sort: function(nodes, dir, width) {
60-
if (!width) {
59+
sort: function(nodes, dir, column) {
60+
if (!column) {
6161
var widths = nodes.map(function(node) { return node.x + node.width; });
62-
width = Math.max.apply(Math, widths);
62+
column = Math.max.apply(Math, widths);
6363
}
6464

6565
if (dir === -1)
66-
return Utils.sortBy(nodes, function(n) { return -(n.x + n.y * width); });
66+
return Utils.sortBy(nodes, function(n) { return -(n.x + n.y * column); });
6767
else
68-
return Utils.sortBy(nodes, function(n) { return (n.x + n.y * width); });
68+
return Utils.sortBy(nodes, function(n) { return (n.x + n.y * column); });
6969
},
7070

7171
createStylesheet: function(id) {
@@ -721,6 +721,7 @@
721721
cellHeightUnit: 'px',
722722
disableOneColumnMode: opts.disableOneColumnMode || false,
723723
oneColumnModeClass: opts.oneColumnModeClass || 'grid-stack-one-column-mode',
724+
oneColumnModeDomSort: opts.oneColumnModeDomSort,
724725
ddPlugin: null
725726
});
726727

@@ -1823,20 +1824,37 @@
18231824
* Called to scale the widget width & position up/down based on the column change.
18241825
* Note we store previous layouts (especially original ones) to make it possible to go
18251826
* from say 12 -> 1 -> 12 and get back to where we were.
1827+
*
1828+
* oldColumn: previous number of columns
1829+
* column: new column number
1830+
* nodes?: different sorted list (ex: DOM order) instead of current list
18261831
*/
1827-
GridStackEngine.prototype._updateNodeWidths = function(oldColumn, column) {
1828-
if (this.nodes.length === 0 || oldColumn === column) { return; }
1829-
var nodes = Utils.sort(this.nodes, -1, oldColumn); // current column reverse sorting so we can insert last to front (limit collision)
1832+
GridStackEngine.prototype._updateNodeWidths = function(oldColumn, column, nodes) {
1833+
if (!this.nodes.length || oldColumn === column) { return; }
18301834

18311835
// cache the current layout in case they want to go back (like 12 -> 1 -> 12) as it requires original data
1832-
var copy = [nodes.length];
1833-
nodes.forEach(function(n, i) {copy[i] = {x: n.x, y: n.y, width: n.width, _id: n._id}}); // only thing we change is x,y,w and id to find it back
1836+
var copy = [this.nodes.length];
1837+
this.nodes.forEach(function(n, i) {copy[i] = {x: n.x, y: n.y, width: n.width, _id: n._id}}); // only thing we change is x,y,w and id to find it back
18341838
this._layouts = this._layouts || []; // use array to find larger quick
18351839
this._layouts[oldColumn] = copy;
18361840

1837-
// see if we have cached previous layout. if NOT and we are going up in size start with the largest layout as down-scaling is more accurate
1838-
var lastIndex = this._layouts.length - 1;
1841+
// if we're going to 1 column and using DOM order rather than default sorting, then generate that layout
1842+
if (column === 1 && nodes && nodes.length) {
1843+
var top = 0;
1844+
nodes.forEach(function(n) {
1845+
n.x = 0;
1846+
n.width = 1;
1847+
n.y = Math.max(n.y, top);
1848+
top = n.y + n.height;
1849+
});
1850+
} else {
1851+
nodes = Utils.sort(this.nodes, -1, oldColumn); // current column reverse sorting so we can insert last to front (limit collision)
1852+
}
1853+
1854+
// see if we have cached previous layout.
18391855
var cacheNodes = this._layouts[column] || [];
1856+
// if not AND we are going up in size start with the largest layout as down-scaling is more accurate
1857+
var lastIndex = this._layouts.length - 1;
18401858
if (cacheNodes.length === 0 && column > oldColumn && column < lastIndex) {
18411859
cacheNodes = this._layouts[lastIndex] || [];
18421860
if (cacheNodes.length) {
@@ -1872,13 +1890,13 @@
18721890
var ratio = column / oldColumn;
18731891
nodes.forEach(function(node) {
18741892
if (!node) return;
1875-
node.x = Math.round(node.x * ratio);
1876-
node.width = (oldColumn === 1 ? 1 : (Math.round(node.width * ratio) || 1));
1893+
node.x = (column === 1 ? 0 : Math.round(node.x * ratio));
1894+
node.width = ((column === 1 || oldColumn === 1) ? 1 : (Math.round(node.width * ratio) || 1));
18771895
newNodes.push(node);
18781896
});
1879-
newNodes = Utils.sort(newNodes, -1, column);
18801897

18811898
// finally relayout them in reverse order (to get correct placement)
1899+
newNodes = Utils.sort(newNodes, -1, column);
18821900
this._ignoreLayoutsNodeChange = true;
18831901
this.batchUpdate();
18841902
this.nodes = []; // pretend we have no nodes to start with (we use same structures) to simplify layout
@@ -1913,9 +1931,19 @@
19131931
this.container.addClass('grid-stack-' + column);
19141932
this.opts.column = this.grid.column = column;
19151933

1916-
// update the items now
19171934
if (doNotPropagate === true) { return; }
1918-
this.grid._updateNodeWidths(oldColumn, column);
1935+
1936+
// update the items now - see if the dom order nodes should be passed instead (else default to current list)
1937+
var domNodes;
1938+
if (this.opts.oneColumnModeDomSort && column === 1) {
1939+
domNodes = [];
1940+
this.container.children('.' + this.opts.itemClass).each(function(index, el) {
1941+
var node = $(el).data('_gridstack_node');
1942+
if (node) { domNodes.push(node); }
1943+
});
1944+
if (!domNodes.length) { domNodes = undefined; }
1945+
}
1946+
this.grid._updateNodeWidths(oldColumn, column, domNodes);
19191947

19201948
// and trigger our event last...
19211949
this.grid._ignoreLayoutsNodeChange = true;

0 commit comments

Comments
 (0)