dojox.grid.EnhancedGrid¶
Project owner: | Nathan Toone |
---|---|
Available: | since V.1.4 |
Enhanced DataGrid adds numerous useful features to dojox.grid.
Contents
Introduction¶
EnhancedGrid (dojox.grid.EnhancedGrid) provides a rich set of features that enhance the capabilities of base DataGrid. The following accessible enhancements are implemented in Dojo 1.4:
- Nested Sorting
- Built-in support for Indirect Selection (radio buttons and check boxes)
- Declarative context menus
- Selecting multiple rows or columns by swiping
- Moving multiple rows or columns with drag-n-drop
EnhancedGrid features are implemented as plugins which can be loaded on demand. As a result, the required features must first declared before they can be used.
<script type="text/javascript">
dojo.require("dojox.grid.EnhancedGrid");
dojo.require("dojox.grid.enhanced.plugins.DnD");
dojo.require("dojox.grid.enhanced.plugins.Menu");
dojo.require("dojox.grid.enhanced.plugins.NestedSorting");
dojo.require("dojox.grid.enhanced.plugins.IndirectSelection");
dojo.require("dojox.data.CsvStore");
dojo.addOnLoad(function(){
// our test data store for this example:
var store = new dojox.data.CsvStore({ url: '{{ dataUrl }}dojox/grid/tests/support/movies.csv' });
// set the layout structure:
var layout = [
{ field: 'Title', name: 'Title of Movie', width: '200px' },
{ field: 'Year', name: 'Year', width: '50px' },
{ field: 'Producer', name: 'Producer', width: 'auto' }
];
// create a new grid:
var grid = new dojox.grid.EnhancedGrid({
query: { Title: '*' },
store: store,
rowSelector: '20px',
structure: layout,
plugins : {nestedSorting: true, dnd: true, indirectSelection: {name: "Selection", width:"70px", styles:"text-align: center;"}}
}, document.createElement('div'));
// append the new grid to the div "gridContainer4":
dojo.byId("gridDiv").appendChild(grid.domNode);
// Call startup, in order to render the grid:
grid.startup();
});
</script>
<div id="gridDiv" style="width: 100%; height: 100%;"></div>
<style type="text/css">
@import "{{ baseUrl }}dojo/resources/dojo.css";
@import "{{ baseUrl }}dijit/themes/{{ theme }}/{{ theme }}.css";
@import "{{ baseUrl }}dojox/grid/enhanced/resources/{{ theme }}EnhancedGrid.css";
@import "{{ baseUrl }}dojox/grid/enhanced/resources/EnhancedGrid_rtl.css";
.dojoxGrid table {
margin: 0;
}
html, body {
width: 100%;
height: 100%;
margin: 0;
}
</style>
Usage¶
The following steps show a typical usage of EnhancedGrid:
- Import related CSS
1 2 3 4 5 | <style type="text/css">
@import "../../../../dijit/themes/claro/claro.css";
@import "../../enhanced/resources/claroEnhancedGrid.css";
...
</style>
|
- Declare required feature plugins
1 2 3 4 5 6 7 8 9 10 11 12 13 | <script type="text/javascript">
// Required for all Enhanced features
dojo.require("dojox.grid.EnhancedGrid");
// Row/Column drag-drop feature
dojo.require("dojox.grid.enhanced.plugins.DnD");
// Declarative pop-up menu feature
dojo.require("dojox.grid.enhanced.plugins.Menu");
// Nested sorting feature
dojo.require("dojox.grid.enhanced.plugins.NestedSorting");
// Indirect selection(check box/radio button selection) feature
dojo.require("dojox.grid.enhanced.plugins.IndirectSelection");
...
</script>
|
- Use features:
1 2 3 4 5 6 7 8 9 | <div id="grid" dojoType="dojox.grid.EnhancedGrid"
plugins="{nestedSorting: true, dnd: true, indirectSelection: true, // Each required feature must be turned on
menus:{
headerMenu:'headerMenu', //References menus defined declaratively below
rowMenu:'rowMenu',
cellMenu:'cellMenu',
selectedRegionMenu:'selectedRegionMenu'}}"
...>
</div>
|
Nested Sorting¶
This feature enhances the single sorting feature of base DataGrid. Nested sorting allows users to sort on one or more columns concurrently and also control the sort direction and order. Finally, columns can be removed from the sort without disturbing the rest of the sort.
<script type="text/javascript">
dojo.require("dojox.grid.EnhancedGrid");
dojo.require("dojox.grid.enhanced.plugins.NestedSorting");
dojo.require("dojox.data.CsvStore");
dojo.addOnLoad(function(){
// our test data store for this example:
var store = new dojox.data.CsvStore({ url: '{{ dataUrl }}dojox/grid/tests/support/movies.csv' });
// set the layout structure:
var layout = [
{ field: 'Title', name: 'Title of Movie', width: '200px' },
{ field: 'Year', name: 'Year', width: '50px' },
{ field: 'Producer', name: 'Producer', width: 'auto' }
];
// create a new grid:
var grid = new dojox.grid.EnhancedGrid({
query: { Title: '*' },
store: store,
clientSort: true,
rowSelector: '20px',
structure: layout,
plugins : {nestedSorting: true}
}, document.createElement('div'));
// append the new grid to the div "gridContainer4":
dojo.byId("gridDiv").appendChild(grid.domNode);
// Call startup, in order to render the grid:
grid.startup();
});
</script>
<div id="gridDiv" style="width: 100%; height: 100%;"></div>
<style type="text/css">
@import "{{ baseUrl }}dojox/grid/enhanced/resources/{{ theme }}EnhancedGrid.css";
@import "{{ baseUrl }}dojox/grid/enhanced/resources/EnhancedGrid_rtl.css";
.dojoxGrid table {
margin: 0;
}
html, body {
width: 100%;
height: 100%;
margin: 0;
}
</style>
Usage¶
Using the nested sorting feature is pretty simple as shown below:
- Declare nested sorting feature plugin
1 2 3 4 5 | <script type="text/javascript">
dojo.require("dojox.grid.EnhancedGrid");
dojo.require("dojox.grid.enhanced.plugins.NestedSorting");
...
</script>
|
- Use nested sorting feature
...with HTML markup
1 2 | <div id="grid" store="store1" dojoType="dojox.grid.EnhancedGrid" plugins="{nestedSorting: true}" >
</div>
|
...with JavaScript
1 2 3 | <script>
var grid = new dojox.grid.EnhancedGrid({id: "grid", store: "store1", plugins: {nestedSorting: true}, ...}, dojo.byId("gridDiv"));
</script>
|
When nested sorting is enabled, you can also use comparatorMap for custom sorting; see dojo.data.ItemFileReadStore on DojoCampus.org for more details.
Scenario¶
The following are typical scenarios using nested sorts:
- When there is no sorting established, a unary (single) sort caret is shown when the mouse hovers over a column. The upward direction of the caret reflects that this will result in an ascending sort.
- Once the sort choice is selected for the 'Genre' column, the grid rows will be sorted ascending based on by the values in Genre. Note that the keyboard focus moves to the sort choice in response to the mouse click. The graphical label of the sort choice is a downward caret since the function would be a descending sort.
- Then the nested sort tip is shown when the mouse hovers over a other column headers.
- Clicking region "A" in the figure below will execute a nested sort, and the rows will be sorted by Artist in this example within Genre.
- Clicking region "B" will reset the sort, and the rows will be sorted by Artist alone.
- Once a column is sorted ascending, the sort choice changes to a sort descending choice.
- Once a column is sorted descending, the sort choice changes to a 'remove sort' function (see the figure below). When a column is removed from the sort, other columns in the sort will be adjusted to reflect the new sort order. For example, Year would become the second column in the sort if it had previously been the third.
To summarize, the sort choice cycles among sort-ascending, sort-descending, and remove sort functions.
There is no limit to the number of columns that may be in the sort.
Accessibility¶
Keyboard Support¶
Key | Action |
---|---|
LEFT/RIGHT arrow keys | Moves the keyboard focus among column headers and regions within a column header |
SPACE key | Chooses the sorting choice with the keyboard focus |
- The above keys are only effective when keyboard focus is within the column headers.
Screen Readers¶
ARIA attributes "aria-label" and "aria-sort" are used for screen readers.
Region | ARIA Attribute | ARIA Attribute Value |
---|---|---|
Select region | aria-label | Column name |
Unary sort choice | aria-sort | Sorting state, e.g. "descending" |
aria-label |
|
|
Nested sort choice | aria-sort | Sorting state, e.g. "descending" |
aria-label |
|
Note: In Firefox v.3.5, JAWS10 doesn't announce all the above ARIA attributes appropriately. This will be addressed when newer JAWS and Firefox versions are released.
Built-in Support for Indirect Selection¶
This feature provides indirect row selection support either through
- Radio buttons - for single row selection, and
- Check boxes - for multiple row selections
Please note indirect selection is completely dependent on the selection mode of EnhancedGrid so check boxes are used for "extended" and "multiple" selection mode ("extended" is the default mode), and radio buttons are used for "single" selection mode. For more details of Grid selection modes, please refer to the specification of the base Grid.
<script type="text/javascript">
dojo.require("dojox.grid.EnhancedGrid");
dojo.require("dojox.grid.enhanced.plugins.IndirectSelection");
dojo.require("dojox.data.CsvStore");
dojo.addOnLoad(function(){
// our test data store for this example:
var store = new dojox.data.CsvStore({ url: '{{ dataUrl }}dojox/grid/tests/support/movies.csv' });
// set the layout structure:
var layout = [
{ field: 'Title', name: 'Title of Movie', width: '200px' },
{ field: 'Year', name: 'Year', width: '50px' },
{ field: 'Producer', name: 'Producer', width: 'auto' }
];
// create a new grid:
var grid = new dojox.grid.EnhancedGrid({
query: { Title: '*' },
store: store,
clientSort: true,
rowSelector: '20px',
structure: layout,
plugins : {indirectSelection: {name: "Selection", width:"70px", styles:"text-align: center;"}}
}, document.createElement('div'));
// append the new grid to the div "gridContainer4":
dojo.byId("gridDiv").appendChild(grid.domNode);
// Call startup, in order to render the grid:
grid.startup();
});
</script>
<div id="gridDiv" style="width: 100%; height: 100%;"></div>
<style type="text/css">
@import "{{ baseUrl }}dojox/grid/enhanced/resources/{{ theme }}EnhancedGrid.css";
@import "{{ baseUrl }}dojox/grid/enhanced/resources/EnhancedGrid_rtl.css";
.dojoxGrid table {
margin: 0;
}
html, body {
width: 100%;
height: 100%;
margin: 0;
}
</style>
Usage¶
- Declare indirect selection feature plugin
1 2 3 4 5 | <script type="text/javascript">
dojo.require("dojox.grid.EnhancedGrid");
dojo.require("dojox.grid.enhanced.plugins.IndirectSelection");
...
</script>
|
- Use indirect selection feature with check boxes
... with HTML markup
1 2 | <div id="grid" dojoType="dojox.grid.EnhancedGrid" plugins="{indirectSelection: true}" >
</div>
|
... with JavaScript
1 2 3 | <script>
var grid = new dojox.grid.EnhancedGrid({id: "grid", plugins: {indirectSelection: true}, ...}, dojo.byId('gridDiv'));
</script>
|
- Use indirect selection feature with radio buttons
... with HTML markup
1 2 | <div id="grid" dojoType="dojox.grid.EnhancedGrid" plugins="{indirectSelection: true}" selectionMode="single" ... >
</div>
|
... with JavaScript
1 2 3 | <script>
var grid = new dojox.grid.EnhancedGrid({id: "grid", plugins: {indirectSelection: true}, selectionMode: "single", ...}, dojo.byId('gridDiv'));
</script>
|
- It is unlikely that the row headers will be desired when indirect selection is used. The following code removes the row headers from the grid.
1 2 3 4 5 6 7 | //with HTML markup
<div id="grid" dojoType="dojox.grid.EnhancedGrid" plugins="{indirectSelection: true}" rowSelector="0px" ... />
//with Javascript
<script>
var grid = new dojox.grid.EnhancedGrid({id: "grid", plugins: {indirectSelection: true}, rowSelector: "0px", ...}, dojo.byId('gridDiv'));
</script>
|
Scenario¶
- Indirect selection by radio buttons
- Indirect selection by check boxes
Besides selecting or deselecting rows by clicking on check boxes, the SHIFT key can be held during the 2nd click to select or deselect a range of rows.
- An additional selection technique is to swipe through check boxes (mouse down on the first, drag through the adjacent check boxes and then release on the last).
Accessibility¶
Keyboard Support¶
Key | Action |
---|---|
UP/Down arrow keys | Navigate keyboard focus across cells that contain radio buttons or check boxes |
SPACE key |
|
SHIFT + Click SHIFT + SPACE key | Select or de-select a range of rows |
SHIFT+ UP/Down arrow keys | Extend the selection or de-selection - only for check boxes . |
- The above keys are only effective when keyboard focus is in the first column that contains radio buttons or check boxes.
Note that extended selection is also enabled through the row headers as well.
Tips¶
- When the "Indirect Selection" feature is enabled, you could handle row selection programmatically as follows.
1 2 3 4 5 | <script>
for(var i = 0; i < selectedRows.length/*Array of selected row index*/; i++){
grid.rowSelectCell.toggleRow(selectedRows[i], true);
}
</script>
|
- When in non-‘single’ selection mode, it’s also easy to select or deselect all rows by:
1 2 3 | <script>
dijit.byId("grid").rowSelectCell.toggleAllSelection(true|false);
</script>
|
- Another handy usage is to enable or disable a check box or radio button for a certain row by:
1 2 3 | <script>
dijit.byId('grid').rowSelectCell.setDisabled(rowIndex, true|false);
</script>
|
- A topic named "rowSelectionChangedTopic" will be published when row selections are changed. The topic can be subscribed to with the following code.
1 | dojo.subscribe(dijit.byId('grid').rowSelectionChangedTopic, function(){...});
|
- You can check whether a certain row is selected with the following code.
1 | dijit.byId('grid').selection.selected[rowIndex] // returns true or false
|
- It's also possible to make some styling customizations for the indirect selection column.
1 | <div id="grid" dojoType="dojox.grid.EnhancedGrid" plugins="{indirectSelection:{name:'Selection',width:'70px',styles:'text-align:right;'}}" ...></div>
|
or
1 2 3 | <script>
var grid = new dojox.grid.EnhancedGrid({id:"grid", plugins:{indirectSelection:{name:"Selection",width:"70px",styles:"text-align:center;"}, ...}, dojo.byId('gridDiv'));
</script>
|
Selecting Multiple Rows/Columns with Swipe¶
This feature provides a mechanism to select row(s) and column(s) via mouse clicking, swiping or keyboards.
Note:
- This feature is implemented as part of the "DnD" plugin of EnhancedGrid.
- Row headers and column select regions are the only places where this feature is effective.
The following figure shows a sample of row headers and column select regions
As noted above, swipe-select is also possible when the check box mode of Indirect Selection is used for row selection.
<script type="text/javascript">
dojo.require("dojox.grid.EnhancedGrid");
dojo.require("dojox.grid.enhanced.plugins.DnD");
dojo.require("dojox.grid.enhanced.plugins.NestedSorting");
dojo.require("dojox.data.CsvStore");
dojo.addOnLoad(function(){
// our test data store for this example:
var store = new dojox.data.CsvStore({ url: '{{ dataUrl }}dojox/grid/tests/support/movies.csv' });
// set the layout structure:
var layout = [
{ field: 'Title', name: 'Title of Movie', width: '200px' },
{ field: 'Year', name: 'Year', width: '50px' },
{ field: 'Producer', name: 'Producer', width: 'auto' }
];
// create a new grid:
var grid = new dojox.grid.EnhancedGrid({
query: { Title: '*' },
store: store,
clientSort: true,
rowSelector: '20px',
structure: layout,
plugins : {dnd: true}
}, document.createElement('div'));
// append the new grid to the div "":
dojo.byId("gridDiv").appendChild(grid.domNode);
// Call startup, in order to render the grid:
grid.startup();
});
</script>
<div id="gridDiv" style="width: 100%; height: 100%;"></div>
<style type="text/css">
@import "{{ baseUrl }}dojox/grid/enhanced/resources/{{ theme }}EnhancedGrid.css";
@import "{{ baseUrl }}dojox/grid/enhanced/resources/EnhancedGrid_rtl.css";
.dojoxGrid table {
margin: 0;
}
html, body {
width: 100%;
height: 100%;
margin: 0;
}
</style>
Usage¶
To use this feature, you need to first enable the "DnD" plugin.
- Declare DnD feature plugin
1 2 3 4 5 6 | <script type="text/javascript">
dojo.require("dojox.grid.EnhancedGrid");
dojo.require("dojox.grid.enhanced.plugins.DnD");
dojo.require("dojox.grid.enhanced.plugins.NestedSorting");//This is a must as DnD depends on NestedSorting feature
...
</script>
|
- To use DnD feature
... with HTML markup
1 | <div id="grid" store="store1" dojoType="dojox.grid.EnhancedGrid" plugins="{dnd: true}" rowSelector="20px" ... ></div>
|
... with JavaScript
1 | var grid = new dojox.grid.EnhancedGrid({id: "grid", store: "store1", plugins: {dnd: true}, rowSelector: "20px", ...}, dojo.byId("gridDiv"));
|
Scenario¶
Selecting rows/columns via mouse clicking/keyboard¶
You can also select multiple non-adjacent rows/columns by holding CTRL key or select a range of adjacent rows/columns by holding SHIFT key and selecting another row. These techniques can be used with either the row headers or checkboxes for multiple row selection.
- Selecting rows/columns by swiping.
Swiping is a useful technique for selecting multiple contiguous rows or columns.
Accessibility¶
Keyboard Support¶
Key | Action |
---|---|
UP/Down arrow keys | Navigate keyboard focus across row headers |
Left/Right arrow keys | Navigate keyboard focus across column headers |
SPACE key | Select a row or column |
SHIFT+ Left/Right arrow keys | Extend the column selection or de-selection |
SHIFT + UP/Down arrow keys | Extend the row selection or de-selection |
- The above key bindings are only effective when keyboard focus is in row headers or select regions of column headers.
Tips¶
- When "DnD" feature is enabled but "Indirect Selection" not enabled, row selection can be handled programmatically the same way as base DataGrid:
1 2 3 | for(var i = 0; i < selectedRows.length/*Array of selected row index*/; i++){
dijit.byId('grid').selection.addToSelection(selectedRows[i]);
}
|
- There are preconditions to using the "DnD" feature: * The "NestedSorting" feature must be enabled to use the "DnD" feature. * "RowSelector" should be used for "DnD", e.g.,
1 | <div dojoType="dojox.grid.EnhancedGrid" plugins='{dnd: true, ...}}' rowSelector="20px" .../>
|
- When the "DnD" feature is enabled, whether a column is selected can be determined by:
1 | dijit.byId('grid').select.selectedColumns[columnIndex] // returns true or false , for column
|
- A topic named "rowSelectionChangedTopic" will be published when row selections are changed. You can subscribe the topic as:
1 | dojo.subscribe(dijit.byId('grid').rowSelectionChangedTopic, function(){...});
|
Drag-n-drop: rows, columns - MOVE¶
This feature is an enhancement to the single column moving feature of base DataGrid. Once rows or columns are selected, they can be moved to the target position by dragging them.
Note:
- This feature is implemented as part of the "DnD" plugin of EnhancedGrid.
- Rows and columns must be selected before being dragged.
<script type="text/javascript">
dojo.require("dojox.grid.EnhancedGrid");
dojo.require("dojox.grid.enhanced.plugins.DnD");
dojo.require("dojox.grid.enhanced.plugins.NestedSorting");
dojo.require("dojox.data.CsvStore");
dojo.addOnLoad(function(){
// our test data store for this example:
var store = new dojox.data.CsvStore({ url: '{{ dataUrl }}dojox/grid/tests/support/movies.csv' });
// set the layout structure:
var layout = [
{ field: 'Title', name: 'Title of Movie', width: '200px' },
{ field: 'Year', name: 'Year', width: '50px' },
{ field: 'Producer', name: 'Producer', width: 'auto' }
];
// create a new grid:
var grid = new dojox.grid.EnhancedGrid({
query: { Title: '*' },
store: store,
clientSort: true,
rowSelector: '20px',
structure: layout,
plugins : {dnd: true}
}, document.createElement('div'));
// append the new grid to the div "":
dojo.byId("gridDiv").appendChild(grid.domNode);
// Call startup, in order to render the grid:
grid.startup();
});
</script>
<div id="gridDiv" style="width: 100%; height: 100%;"></div>
<style type="text/css">
@import "{{ baseUrl }}dojox/grid/enhanced/resources/{{ theme }}EnhancedGrid.css";
@import "{{ baseUrl }}dojox/grid/enhanced/resources/EnhancedGrid_rtl.css";
.dojoxGrid table {
margin: 0;
}
html, body {
width: 100%;
height: 100%;
margin: 0;
}
</style>
Usage¶
See the usage section for "Selecting rows/columns via swipe".
Scenario¶
- Moving contiguous rows/columns.
Moving discontiguous rows/columns.
Discontiguous rows and columns can be moved using drag-drop as well. The moved columns and rows will be adjacent, in their original relative order, after the move.
See also¶
-
The base grid
-
This grid offers support for collapsable rows and model-based (dijit.tree.ForestStoreModel) structure