Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions Grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,11 @@ function(kernel, declare, listen, has, put, List, miscUtil){
// respond to click, space keypress, or enter keypress
if(event.type == "click" || event.keyCode == 32 /* space bar */ || (!has("opera") && event.keyCode == 13) /* enter */){
var target = event.target,
field, sort, newSort, eventObj;
newSort, eventObj;
do{
if(target.sortable){
// If the click is on the same column as the active sort,
// reverse sort direction
newSort = [{
attribute: (field = target.field || target.columnId),
descending: (sort = grid._sort[0]) && sort.attribute == field &&
!sort.descending
}];
// Construct a new sort based on the targeted column
newSort = grid._constructSort(target);

// Emit an event with the new sort
eventObj = {
Expand Down Expand Up @@ -287,6 +282,22 @@ function(kernel, declare, listen, has, put, List, miscUtil){

this.inherited(arguments);
},

_constructSort: function(columnHeader){
// summary:
// Construct a new sort array from the given column header node. This
// will be called after the header is clicked *if* the column in
// question is sortable.

var field, sort;
// If the click is on the same column as the active sort,
// reverse sort direction
return [{
attribute: (field = columnHeader.field || columnHeader.columnId),
descending: (sort = this._sort[0]) && sort.attribute == field &&
!sort.descending
}];
},

_setSort: function(property, descending){
// summary:
Expand Down
53 changes: 53 additions & 0 deletions extensions/NestedSort.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
define(["dojo/_base/declare", "dojo/_base/lang"],
function(declare, lang){
/*
* Nested Sort plugin for dgrid
*
* A plugin that allows your grid to have multi-column sorts, thus giving users
* the experience of stable sorting. The behaviors are:
*
* 1. Clicking on a header that's already at the start of the sort list:
* Toggles 'descending' for that column.
* 2. Clicking on a header that's not in the sort list:
* Add it to the start of the sort list, ascending.
* 3. Clicking on a header that's down in the sort list:
* Move it to the front of the list without changing 'descending'.
*
*/

return declare(null, {
// sortDepthLimit: Integer
// The maximum nested sort depth. The default of 'null' means 'no limit'.
sortDepthLimit: null,

_constructSort: function (columnHeader) {
// summary:
// Construct a new sort array based on the given column header node.
// Instead of always creating an array of one element like Grid.js,
// this implementation maintains a stable sort with multiple elements.

var sort = lang.clone(this.get('sort') || []);
var field = columnHeader.field || columnHeader.columnId;
for (var i = 0; i < sort.length; i++) {
var col = sort[i];
if (col.attribute === field) {
if (i === 0) {
// If the old one was already at the top, toggle descending.
col.descending = !col.descending;
} else {
sort.splice(i, 1); // remove from middle
sort.splice(0, 0, col); // add to the start
}
break;
}
}
if (i >= sort.length) {
sort.splice(0, 0, { attribute: field, descending: false });
}
if (this.sortDepthLimit && sort.length > this.sortDepthLimit) {
sort.splice(this.sortDepthLimit);
}
return sort;
}
});
});
3 changes: 2 additions & 1 deletion test/intern/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ define([
'intern/node_modules/dojo/has!host-browser?./core/setClass',
'intern/node_modules/dojo/has!host-browser?./mixins/Keyboard',
'intern/node_modules/dojo/has!host-browser?./mixins/Selection',
'intern/node_modules/dojo/has!host-browser?./mixins/extensions/NestedSort',
'intern/node_modules/dojo/has!host-browser?./core/stores',
'intern/node_modules/dojo/has!host-browser?./core/_StoreMixin',
'intern/node_modules/dojo/has!host-browser?./core/OnDemand-removeRow'
], function(){});
], function(){});
140 changes: 140 additions & 0 deletions test/intern/mixins/extensions/NestedSort.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
define([
"intern!tdd",
"intern/chai!assert",
"dgrid/Grid",
"dgrid/extensions/NestedSort",
"dojo/_base/declare",
"dgrid/test/data/base"
], function(test, assert, Grid, NestedSort, declare){
var columns = {
col1: "Column 1",
col3: "Column 3",
col5: "Column 5"
},
grid;

test.suite("NestedSort (Grid)", function(){
test.before(function(){
grid = new (declare([Grid, NestedSort]))({
columns: columns,
sort: "id",
store: testStore
});
document.body.appendChild(grid.domNode);
grid.startup();
});

test.after(function(){
grid.destroy();
});

test.beforeEach(function(){
grid.set("sort", "id");
grid.set("sortDepthLimit", null);
});

test.test("grid.sort unaffected", function(){
assert.deepEqual(grid.get("sort"), [
{ attribute: "id", descending: undefined }
], "default sort did not return expected value");

grid.set("sort", "col1");
assert.deepEqual(grid.get("sort"), [
{ attribute: "col1", descending: undefined }
], "sort of one element did not return expected value");

var sort = [
{ attribute: "id", descending: true },
{ attribute: "col1", descending: false }
];
grid.set("sort", sort);
assert.deepEqual(grid.get("sort"), sort,
"sort of multiple elements did not return expected value");
});

test.test("column sorting - insert new", function(){
grid.columns["col1"].headerNode.click();
assert.deepEqual(grid.get("sort"), [
{ attribute: "col1", descending: false },
{ attribute: "id", descending: undefined }
], "sort incorrect after one column click");

grid.columns["col5"].headerNode.click();
assert.deepEqual(grid.get("sort"), [
{ attribute: "col5", descending: false },
{ attribute: "col1", descending: false },
{ attribute: "id", descending: undefined }
], "sort incorrect after two column clicks");
});

test.test("column sorting - toggle first", function(){
grid.set("sort", [
{ attribute: "col1", descending: undefined },
{ attribute: "col5", descending: false }
]);

grid.columns["col1"].headerNode.click();
assert.deepEqual(grid.get("sort"), [
{ attribute: "col1", descending: true },
{ attribute: "col5", descending: false }
], "sort not changed to descending");

grid.columns["col1"].headerNode.click();
assert.deepEqual(grid.get("sort"), [
{ attribute: "col1", descending: false },
{ attribute: "col5", descending: false }
], "sort not changed to ascending");
});

test.test("column sorting - move to front", function(){
grid.set("sort", [
{ attribute: "col1", descending: undefined },
{ attribute: "col3", descending: true },
{ attribute: "col5", descending: false }
]);

grid.columns["col3"].headerNode.click();
assert.deepEqual(grid.get("sort"), [
{ attribute: "col3", descending: true },
{ attribute: "col1", descending: undefined },
{ attribute: "col5", descending: false }
], "sort not changed to col3");

grid.columns["col5"].headerNode.click();
assert.deepEqual(grid.get("sort"), [
{ attribute: "col5", descending: false },
{ attribute: "col3", descending: true },
{ attribute: "col1", descending: undefined }
], "sort not changed to col5");

grid.columns["col1"].headerNode.click();
assert.deepEqual(grid.get("sort"), [
{ attribute: "col1", descending: undefined },
{ attribute: "col5", descending: false },
{ attribute: "col3", descending: true }
], "sort not changed to col1");
});

test.test("column sorting - sortDepthLimit", function(){
grid.set("sortDepthLimit", 2);

grid.columns["col1"].headerNode.click();
assert.deepEqual(grid.get("sort"), [
{ attribute: "col1", descending: false },
{ attribute: "id", descending: undefined }
], "sort incorrect after one column click");

grid.columns["col5"].headerNode.click();
assert.deepEqual(grid.get("sort"), [
{ attribute: "col5", descending: false },
{ attribute: "col1", descending: false }
], "sort incorrect after two column clicks");

grid.columns["col3"].headerNode.click();
assert.deepEqual(grid.get("sort"), [
{ attribute: "col3", descending: false },
{ attribute: "col5", descending: false }
], "sort incorrect after three column clicks");
});
});
});