summaryrefslogtreecommitdiff
path: root/js/dojo/dojox/grid/enhanced
diff options
context:
space:
mode:
authorTristan Zur <tzur@web.web.ccwn.org>2014-03-27 22:27:47 +0100
committerTristan Zur <tzur@web.web.ccwn.org>2014-03-27 22:27:47 +0100
commitb62676ca5d3d6f6ba3f019ea3f99722e165a98d8 (patch)
tree86722cb80f07d4569f90088eeaea2fc2f6e2ef94 /js/dojo/dojox/grid/enhanced
Initial commit of intern.ccwn.org contentsHEADmaster
Diffstat (limited to 'js/dojo/dojox/grid/enhanced')
-rw-r--r--js/dojo/dojox/grid/enhanced/_Events.js215
-rw-r--r--js/dojo/dojox/grid/enhanced/_FocusManager.js774
-rw-r--r--js/dojo/dojox/grid/enhanced/_Plugin.js172
-rw-r--r--js/dojo/dojox/grid/enhanced/_PluginManager.js275
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/EnhancedGrid.js48
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/Filter.js121
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/Pagination.js56
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ar/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ar/Filter.js90
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ar/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ca/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ca/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ca/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/cs/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/cs/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/cs/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/da/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/da/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/da/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/de/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/de/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/de/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/el/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/el/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/el/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/es/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/es/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/es/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/fi/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/fi/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/fi/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/fr/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/fr/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/fr/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/he/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/he/Filter.js90
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/he/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/hr/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/hr/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/hr/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/hu/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/hu/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/hu/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/it/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/it/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/it/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ja/EnhancedGrid.js16
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ja/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ja/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/kk/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/kk/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/kk/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ko/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ko/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ko/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/nb/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/nb/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/nb/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/nl/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/nl/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/nl/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/pl/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/pl/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/pl/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/pt-br/EnhancedGrid.js16
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/pt-br/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/pt-br/Pagination.js36
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/pt-pt/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/pt-pt/Filter.js90
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/pt-pt/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/pt/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/pt/Filter.js92
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/pt/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ro/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ro/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ro/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ru/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ru/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/ru/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/sk/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/sk/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/sk/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/sl/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/sl/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/sl/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/sv/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/sv/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/sv/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/th/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/th/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/th/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/tr/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/tr/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/tr/Pagination.js24
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/zh-tw/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/zh-tw/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/zh-tw/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/zh/EnhancedGrid.js17
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/zh/Filter.js89
-rw-r--r--js/dojo/dojox/grid/enhanced/nls/zh/Pagination.js25
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/AutoScroll.js182
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/CellMerge.js276
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/Cookie.js362
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/Dialog.js40
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/DnD.js1094
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/Exporter.js243
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/Filter.js173
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/GridSource.js155
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/IndirectSelection.js626
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/Menu.js134
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/NestedSorting.js610
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/Pagination.js974
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/Printer.js292
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/Rearrange.js506
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/Search.js123
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/Selector.js1477
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/_RowMapLayer.js207
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/_SelectionPreserver.js109
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/_StoreLayer.js395
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/exporter/CSVWriter.js88
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/exporter/TableWriter.js160
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/exporter/_ExportWriter.js269
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/filter/ClearFilterConfirm.js46
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/filter/FilterBar.js386
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/filter/FilterBuilder.js81
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/filter/FilterDefDialog.js1252
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/filter/FilterLayer.js411
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/filter/FilterStatusTip.js148
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/filter/_ConditionExpr.js243
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/filter/_DataExprs.js85
-rw-r--r--js/dojo/dojox/grid/enhanced/plugins/filter/_FilterExpr.js248
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/Common.css27
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/Common_rtl.css15
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/DnD.css78
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/DnD_rtl.css12
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/EnhancedGrid.css8
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/EnhancedGrid_rtl.css6
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/Filter.css292
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/Filter_rtl.css84
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/Pagination.css147
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/Pagination_rtl.css68
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/Sorter.css179
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/Sorter_rtl.css78
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/claro/Common.css26
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/claro/EnhancedGrid.css4
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/claro/Filter.css58
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/claroEnhancedGrid.css2
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/images/sprite_icons.pngbin0 -> 2912 bytes
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/tundra/Common.css40
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/tundra/EnhancedGrid.css5
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/tundra/Filter.css38
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/tundra/Sorter.css83
-rw-r--r--js/dojo/dojox/grid/enhanced/resources/tundraEnhancedGrid.css2
-rw-r--r--js/dojo/dojox/grid/enhanced/templates/ClearFilterConfirmPane.html9
-rw-r--r--js/dojo/dojox/grid/enhanced/templates/CriteriaBox.html20
-rw-r--r--js/dojo/dojox/grid/enhanced/templates/FilterBar.html15
-rw-r--r--js/dojo/dojox/grid/enhanced/templates/FilterBoolValueBox.html11
-rw-r--r--js/dojo/dojox/grid/enhanced/templates/FilterDefPane.html27
-rw-r--r--js/dojo/dojox/grid/enhanced/templates/FilterStatusPane.html8
-rw-r--r--js/dojo/dojox/grid/enhanced/templates/Pagination.html18
160 files changed, 18476 insertions, 0 deletions
diff --git a/js/dojo/dojox/grid/enhanced/_Events.js b/js/dojo/dojox/grid/enhanced/_Events.js
new file mode 100644
index 0000000..c461531
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/_Events.js
@@ -0,0 +1,215 @@
+//>>built
+define("dojox/grid/enhanced/_Events", [
+ "dojo/_base/kernel",
+ "dojo/_base/declare",
+ "dojo/keys",
+ "dojo/_base/html",
+ "dojo/_base/event",
+ "dojox/grid/_Events"
+], function(dojo, declare, keys, html, event, _Events){
+
+return declare("dojox.grid.enhanced._Events", null, {
+ // summary:
+ // Overwrite some default events of DataGrid
+ //
+ // description:
+ // Methods are copied or replaced for overwriting, this might be refined once
+ // an overall plugin architecture is set up for DataGrid.
+
+ //_events: Object
+ // Method map cached from dojox.grid._Events().
+ _events: null,
+
+ // headerCellActiveClass: String
+ // css class to apply to grid header cells when activated(mouse down)
+ headerCellActiveClass: 'dojoxGridHeaderActive',
+
+ // cellActiveClass: String
+ // css class to apply to grid content cells when activated(mouse down)
+ cellActiveClass: 'dojoxGridCellActive',
+
+ // rowActiveClass: String
+ // css class to apply to grid rows when activated(mouse down)
+ rowActiveClass: 'dojoxGridRowActive',
+
+ constructor: function(inGrid){
+ //TODO - extend dojox.grid._Events rather than mixin for 1.8
+ this._events = new _Events();
+ //mixin "this" to Grid
+ inGrid.mixin(inGrid, this);
+ },
+ dokeyup: function(e){
+ // summary:
+ // Grid key up event handler.
+ // e: Event
+ // Un-decorated event object
+ this.focus.currentArea().keyup(e);
+ },
+ onKeyDown: function(e){
+ // summary:
+ // Overwritten, see dojox.grid._Events.onKeyDown();
+ if(e.altKey || e.metaKey){ return; }
+ var focus = this.focus;
+ var editing = this.edit.isEditing();
+ switch(e.keyCode){
+ case keys.TAB:
+ if(e.ctrlKey){ return; }
+ focus.tab(e.shiftKey ? -1:1,e);
+ break;
+ case keys.UP_ARROW:
+ case keys.DOWN_ARROW:
+ if(editing){ return; }
+ focus.currentArea().move(e.keyCode == keys.UP_ARROW ? -1 : 1, 0, e);
+ break;
+ case keys.LEFT_ARROW:
+ case keys.RIGHT_ARROW:
+ if(editing){ return; }
+ var offset = (e.keyCode == keys.LEFT_ARROW) ? 1 : -1;
+ if(html._isBodyLtr()){ offset *= -1; }
+ focus.currentArea().move(0, offset, e);
+ break;
+ case keys.F10:
+ if(this.menus && e.shiftKey){
+ this.onRowContextMenu(e);
+ }
+ break;
+ default:
+ focus.currentArea().keydown(e);
+ break;
+ }
+ },
+ //TODO - make the following events more reasonalble - e.g. more accurate conditions
+ //events for row selectors
+ domouseup: function(e){
+ if(e.cellNode){
+ this.onMouseUp(e);
+ }else{
+ this.onRowSelectorMouseUp(e);
+ }
+ },
+ domousedown: function(e){
+ if(!e.cellNode){
+ this.onRowSelectorMouseDown(e);
+ }
+ },
+ onMouseUp: function(e){
+ // summary:
+ // New - Event fired when mouse is up inside grid.
+ // e: Event
+ // Decorated event object that contains reference to grid, cell, and rowIndex
+ this[e.rowIndex == -1 ? "onHeaderCellMouseUp" : "onCellMouseUp"](e);
+ },
+ onCellMouseDown: function(e){
+ // summary:
+ // Overwritten, see dojox.grid._Events.onCellMouseDown()
+ html.addClass(e.cellNode, this.cellActiveClass);
+ html.addClass(e.rowNode, this.rowActiveClass);
+ },
+ onCellMouseUp: function(e){
+ // summary:
+ // New - Event fired when mouse is up inside content cell.
+ // e: Event
+ // Decorated event object that contains reference to grid, cell, and rowIndex
+ html.removeClass(e.cellNode, this.cellActiveClass);
+ html.removeClass(e.rowNode, this.rowActiveClass);
+ },
+ onCellClick: function(e){
+ // summary:
+ // Overwritten, see dojox.grid._Events.onCellClick()
+
+ //invoke dojox.grid._Events.onCellClick()
+ this._events.onCellClick.call(this, e);
+ //move mouse events to the focus manager.
+ this.focus.contentMouseEvent(e);//TODO
+ },
+ onCellDblClick: function(e){
+ // summary:
+ // Overwritten, see dojox.grid._Events.onCellDblClick()
+ if(this.pluginMgr.isFixedCell(e.cell)){ return; }
+ if(this._click.length > 1 && (!this._click[0] || !this._click[1])){
+ this._click[0] = this._click[1] = e;
+ }
+ //invoke dojox.grid._Events.onCellDblClick()
+ this._events.onCellDblClick.call(this, e);
+ },
+ onRowClick: function(e){
+ // summary:
+ // Overwritten, see dojox.grid._Events.onRowClick()
+ this.edit.rowClick(e);
+ if(!e.cell || !this.plugin('indirectSelection')){
+ this.selection.clickSelectEvent(e);
+ }
+ },
+ onRowContextMenu: function(e){
+ // summary:
+ // Overwritten, see dojox.grid._Events.onRowContextMenu()
+ if(!this.edit.isEditing() && this.menus){
+ this.showMenu(e);
+ }
+ },
+ onSelectedRegionContextMenu: function(e){
+ // summary:
+ // New - Event fired when a selected region context menu is accessed via mouse right click.
+ // e: Event
+ // Decorated event object which contains reference to grid and info of selected
+ // regions(selection type - row|column, selected index - [...])
+ if(this.selectedRegionMenu){
+ this.selectedRegionMenu._openMyself({
+ target: e.target,
+ coords: e.keyCode !== keys.F10 && "pageX" in e ? {
+ x: e.pageX,
+ y: e.pageY
+ } : null
+ });
+ event.stop(e);
+ }
+ },
+ onHeaderCellMouseOut: function(e){
+ // summary:
+ // Overwritten, see dojox.grid._Events.onHeaderCellMouseOut()
+ if(e.cellNode){
+ html.removeClass(e.cellNode, this.cellOverClass);
+ html.removeClass(e.cellNode, this.headerCellActiveClass);
+ }
+ },
+ onHeaderCellMouseDown: function(e){
+ // summary:
+ // Overwritten, see dojox.grid._Events.onHeaderCellMouseDown()
+ if(e.cellNode){//TBD - apply to selection region for nested sorting?
+ html.addClass(e.cellNode, this.headerCellActiveClass);
+ }
+ },
+ onHeaderCellMouseUp: function(e){
+ // summary:
+ // New event
+ if(e.cellNode){
+ html.removeClass(e.cellNode, this.headerCellActiveClass);
+ }
+ },
+ onHeaderCellClick: function(e){
+ // summary:
+ // Overwritten, see dojox.grid._Events.onHeaderCellClick()
+ //move focus to header.
+ this.focus.currentArea("header");
+ //invoke dojox.grid._Events.onHeaderCellClick()
+ if(!e.cell.isRowSelector){
+ this._events.onHeaderCellClick.call(this, e);
+ }
+ //move mouse events to the focus manager.
+ this.focus.headerMouseEvent(e);
+ },
+ onRowSelectorMouseDown: function(e){
+ this.focus.focusArea("rowHeader", e);
+ },
+
+ onRowSelectorMouseUp: function(e){},
+
+ //triggered in _View, see Selector plugin
+ onMouseUpRow: function(e){
+ if(e.rowIndex != -1){
+ this.onRowMouseUp(e);
+ }
+ },
+ onRowMouseUp: function(e){}
+});
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/_FocusManager.js b/js/dojo/dojox/grid/enhanced/_FocusManager.js
new file mode 100644
index 0000000..872d089
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/_FocusManager.js
@@ -0,0 +1,774 @@
+//>>built
+define("dojox/grid/enhanced/_FocusManager", [
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "dojo/_base/event",
+ "dojo/_base/sniff",
+ "dojo/_base/html",
+ "dojo/keys",
+ "dijit/a11y",
+ "dijit/focus",
+ "../_FocusManager"
+], function(dojo, lang, declare, array, connect, event, has, html, keys, dijitA11y, dijitFocus, _FocusManager){
+
+var _FocusArea = declare("dojox.grid.enhanced._FocusArea", null, {
+ // summary:
+ // This is a friend class of _FocusManager
+/*=====
+ // name: string
+ // Name of this area.
+ name: "",
+
+ // onFocus: function(event, step)
+ // Called when this area logically gets focus.
+ // event: Event object
+ // May be unavailable, should check before use.
+ // step: Integer
+ // The distance in the tab sequence from last focused area to this area.
+ // returns:
+ // whether this area is successfully focused. If not, the next area will get focus.
+ onFocus: function(event, step){return true;},
+
+ // onBlur: function(event, step)
+ // Called when this area logically loses focus.
+ // event: Event object
+ // May be unavailable, should check before use.
+ // step: Integer
+ // The distance in the tab sequence from this area to the area to focus.
+ // returns:
+ // If Boolean, means whether this area has successfully blurred. If not, the next area to focus is still this one.
+ // If String, means the next area to focus is given by this returned name.
+ onBlur: function(event, step){return true;},
+
+ // onMove: function(rowStep, colStep, event)
+ // Called when focus is moving around within this area.
+ // rowStep: Integer
+ // colStep: Integer
+ // event: Event object
+ // May be unavailable, should check before use.
+ onMove: function(rowStep, colStep, event){},
+
+ // onKey: function(event, isBubble)
+ // Called when some key is pressed when focus is logically in this area.
+ // event: Event object
+ // isBubble: Boolean
+ // Whether is in bubble stage (true) or catch stage (false).
+ // returns:
+ // If you do NOT want the event to propagate any further along the area stack, return exactly false.
+ // So if you return nothing (undefined), this event is still propagating.
+ onKey: function(event, isBubble){return true},
+
+ // getRegions: function()
+ // Define the small regions (dom nodes) in this area.
+ // returns: Array of dom nodes.
+ getRegions: function(){},
+
+ // onRegionFocus: function(event)
+ // Connected to the onfocus event of the defined regions (if any)
+ onRegionFocus: function(event){},
+
+ // onRegionBlur: function(event)
+ // Connected to the onblur event of the defined regions (if any)
+ onRegionBlur: function(event){},
+=====*/
+ constructor: function(area, focusManager){
+ this._fm = focusManager;
+ this._evtStack = [area.name];
+ var dummy = function(){return true;};
+ area.onFocus = area.onFocus || dummy;
+ area.onBlur = area.onBlur || dummy;
+ area.onMove = area.onMove || dummy;
+ area.onKeyUp = area.onKeyUp || dummy;
+ area.onKeyDown = area.onKeyDown || dummy;
+ lang.mixin(this, area);
+ },
+ move: function(rowStep, colStep, evt){
+ if(this.name){
+ var i, len = this._evtStack.length;
+ for(i = len - 1; i >= 0; --i){
+ if(this._fm._areas[this._evtStack[i]].onMove(rowStep, colStep, evt) === false){
+ return false;
+ }
+ }
+ }
+ return true;
+ },
+ _onKeyEvent: function(evt, funcName){
+ if(this.name){
+ var i, len = this._evtStack.length;
+ for(i = len - 1; i >= 0; --i){
+ if(this._fm._areas[this._evtStack[i]][funcName](evt, false) === false){
+ return false;
+ }
+ }
+ for(i = 0; i < len; ++i){
+ if(this._fm._areas[this._evtStack[i]][funcName](evt, true) === false){
+ return false;
+ }
+ }
+ }
+ return true;
+ },
+ keydown: function(evt){
+ return this._onKeyEvent(evt, "onKeyDown");
+ },
+ keyup: function(evt){
+ return this._onKeyEvent(evt, "onKeyUp");
+ },
+ contentMouseEventPlanner: function(){
+ return 0;
+ },
+ headerMouseEventPlanner: function(){
+ return 0;
+ }
+});
+
+return declare("dojox.grid.enhanced._FocusManager", _FocusManager, {
+ _stopEvent: function(evt){
+ try{
+ if(evt && evt.preventDefault){
+ event.stop(evt);
+ }
+ }catch(e){}
+ },
+
+ constructor: function(grid){
+ this.grid = grid;
+ this._areas = {};
+ this._areaQueue = [];
+ this._contentMouseEventHandlers = [];
+ this._headerMouseEventHandlers = [];
+ this._currentAreaIdx = -1;
+ this._gridBlured = true;
+ this._connects.push(connect.connect(grid, "onBlur", this, "_doBlur"));
+ this._connects.push(connect.connect(grid.scroller, "renderPage", this, "_delayedCellFocus"));
+
+ this.addArea({
+ name: "header",
+ onFocus: lang.hitch(this, this.focusHeader),
+ onBlur: lang.hitch(this, this._blurHeader),
+ onMove: lang.hitch(this, this._navHeader),
+ getRegions: lang.hitch(this, this._findHeaderCells),
+ onRegionFocus: lang.hitch(this, this.doColHeaderFocus),
+ onRegionBlur: lang.hitch(this, this.doColHeaderBlur),
+ onKeyDown: lang.hitch(this, this._onHeaderKeyDown)
+ });
+ this.addArea({
+ name: "content",
+ onFocus: lang.hitch(this, this._focusContent),
+ onBlur: lang.hitch(this, this._blurContent),
+ onMove: lang.hitch(this, this._navContent),
+ onKeyDown: lang.hitch(this, this._onContentKeyDown)
+ });
+ this.addArea({
+ name: "editableCell",
+ onFocus: lang.hitch(this, this._focusEditableCell),
+ onBlur: lang.hitch(this, this._blurEditableCell),
+ onKeyDown: lang.hitch(this, this._onEditableCellKeyDown),
+ onContentMouseEvent: lang.hitch(this, this._onEditableCellMouseEvent),
+ contentMouseEventPlanner: function(evt, areas){ return -1; }
+ });
+ this.placeArea("header");
+ this.placeArea("content");
+ this.placeArea("editableCell");
+ this.placeArea("editableCell","above","content");
+ },
+ destroy: function(){
+ for(var name in this._areas){
+ var area = this._areas[name];
+ array.forEach(area._connects, connect.disconnect);
+ area._connects = null;
+ if(area.uninitialize){
+ area.uninitialize();
+ }
+ }
+ this.inherited(arguments);
+ },
+ addArea: function(area){
+ if(area.name && lang.isString(area.name)){
+ if(this._areas[area.name]){
+ //Just replace the original area, instead of remove it, so the position does not change.
+ array.forEach(area._connects, connect.disconnect);
+ }
+ this._areas[area.name] = new _FocusArea(area, this);
+ if(area.onHeaderMouseEvent){
+ this._headerMouseEventHandlers.push(area.name);
+ }
+ if(area.onContentMouseEvent){
+ this._contentMouseEventHandlers.push(area.name);
+ }
+ }
+ },
+ getArea: function(areaName){
+ return this._areas[areaName];
+ },
+ _bindAreaEvents: function(){
+ var area, hdl, areas = this._areas;
+ array.forEach(this._areaQueue, function(name){
+ area = areas[name];
+ if(!area._initialized && lang.isFunction(area.initialize)){
+ area.initialize();
+ area._initialized = true;
+ }
+ if(area.getRegions){
+ area._regions = area.getRegions() || [];
+ array.forEach(area._connects || [], connect.disconnect);
+ area._connects = [];
+ array.forEach(area._regions, function(r){
+ if(area.onRegionFocus){
+ hdl = connect.connect(r, "onfocus", area.onRegionFocus);
+ area._connects.push(hdl);
+ }
+ if(area.onRegionBlur){
+ hdl = connect.connect(r, "onblur", area.onRegionBlur);
+ area._connects.push(hdl);
+ }
+ });
+ }
+ });
+ },
+ removeArea: function(areaName){
+ var area = this._areas[areaName];
+ if(area){
+ this.ignoreArea(areaName);
+ var i = array.indexOf(this._contentMouseEventHandlers, areaName);
+ if(i >= 0){
+ this._contentMouseEventHandlers.splice(i, 1);
+ }
+ i = array.indexOf(this._headerMouseEventHandlers, areaName);
+ if(i >= 0){
+ this._headerMouseEventHandlers.splice(i, 1);
+ }
+ array.forEach(area._connects, connect.disconnect);
+ if(area.uninitialize){
+ area.uninitialize();
+ }
+ delete this._areas[areaName];
+ }
+ },
+ currentArea: function(areaName, toBlurOld){
+ // summary:
+ // Set current area to the one areaName refers.
+ // areaName: String
+ var idx, cai = this._currentAreaIdx;
+ if(lang.isString(areaName) && (idx = array.indexOf(this._areaQueue, areaName)) >= 0){
+ if(cai != idx){
+ this.tabbingOut = false;
+ if(toBlurOld && cai >= 0 && cai < this._areaQueue.length){
+ this._areas[this._areaQueue[cai]].onBlur();
+ }
+ this._currentAreaIdx = idx;
+ }
+ }else{
+ return (cai < 0 || cai >= this._areaQueue.length) ?
+ new _FocusArea({}, this) :
+ this._areas[this._areaQueue[this._currentAreaIdx]];
+ }
+ return null;
+ },
+ placeArea: function(name, pos, otherAreaName){
+ // summary:
+ // Place the area refered by *name* at some logical position relative to an existing area.
+ // example:
+ // placeArea("myarea","before"|"after",...)
+ // placeArea("myarea","below"|"above",...)
+ if(!this._areas[name]){ return; }
+ var idx = array.indexOf(this._areaQueue,otherAreaName);
+ switch(pos){
+ case "after":
+ if(idx >= 0){ ++idx; }
+ //intentional drop through
+ case "before":
+ if(idx >= 0){
+ this._areaQueue.splice(idx,0,name);
+ break;
+ }
+ //intentional drop through
+ default:
+ this._areaQueue.push(name);
+ break;
+ case "above":
+ var isAbove = true;
+ //intentional drop through
+ case "below":
+ var otherArea = this._areas[otherAreaName];
+ if(otherArea){
+ if(isAbove){
+ otherArea._evtStack.push(name);
+ }else{
+ otherArea._evtStack.splice(0,0,name);
+ }
+ }
+ }
+ },
+ ignoreArea: function(name){
+ this._areaQueue = array.filter(this._areaQueue,function(areaName){
+ return areaName != name;
+ });
+ },
+ focusArea: function(/* int|string|areaObj */areaId,evt){
+ var idx;
+ if(typeof areaId == "number"){
+ idx = areaId < 0 ? this._areaQueue.length + areaId : areaId;
+ }else{
+ idx = array.indexOf(this._areaQueue,
+ lang.isString(areaId) ? areaId : (areaId && areaId.name));
+ }
+ if(idx < 0){ idx = 0; }
+ var step = idx - this._currentAreaIdx;
+ this._gridBlured = false;
+ if(step){
+ this.tab(step, evt);
+ }else{
+ this.currentArea().onFocus(evt, step);
+ }
+ },
+ tab: function(step,evt){
+ //console.log("===========tab",step,"curArea",this._currentAreaIdx,"areaCnt",this._areaQueue.length);
+ this._gridBlured = false;
+ this.tabbingOut = false;
+ if(step === 0){
+ return;
+ }
+ var cai = this._currentAreaIdx;
+ var dir = step > 0 ? 1:-1;
+ if(cai < 0 || cai >= this._areaQueue.length){
+ cai = (this._currentAreaIdx += step);
+ }else{
+ var nextArea = this._areas[this._areaQueue[cai]].onBlur(evt,step);
+ if(nextArea === true){
+ cai = (this._currentAreaIdx += step);
+ }else if(lang.isString(nextArea) && this._areas[nextArea]){
+ cai = this._currentAreaIdx = array.indexOf(this._areaQueue,nextArea);
+ }
+ }
+ //console.log("target area:",cai);
+ for(; cai >= 0 && cai < this._areaQueue.length; cai += dir){
+ this._currentAreaIdx = cai;
+ if(this._areaQueue[cai] && this._areas[this._areaQueue[cai]].onFocus(evt,step)){
+ //console.log("final target area:",this._currentAreaIdx);
+ return;
+ }
+ }
+ //console.log("tab out");
+ this.tabbingOut = true;
+ if(step < 0){
+ this._currentAreaIdx = -1;
+ dijitFocus.focus(this.grid.domNode);
+ }else{
+ this._currentAreaIdx = this._areaQueue.length;
+ dijitFocus.focus(this.grid.lastFocusNode);
+ }
+ },
+ _onMouseEvent: function(type, evt){
+ var lowercase = type.toLowerCase(),
+ handlers = this["_" + lowercase + "MouseEventHandlers"],
+ res = array.map(handlers, function(areaName){
+ return {
+ "area": areaName,
+ "idx": this._areas[areaName][lowercase + "MouseEventPlanner"](evt, handlers)
+ };
+ }, this).sort(function(a, b){
+ return b.idx - a.idx;
+ }),
+ resHandlers = array.map(res, function(handler){
+ return res.area;
+ }),
+ i = res.length;
+ while(--i >= 0){
+ if(this._areas[res[i].area]["on" + type + "MouseEvent"](evt, resHandlers) === false){
+ return;
+ }
+ }
+ },
+ contentMouseEvent: function(evt){
+ this._onMouseEvent("Content", evt);
+ },
+ headerMouseEvent: function(evt){
+ this._onMouseEvent("Header", evt);
+ },
+ initFocusView: function(){
+ // summary:
+ // Overwritten
+ this.focusView = this.grid.views.getFirstScrollingView() || this.focusView || this.grid.views.views[0];
+ this._bindAreaEvents();
+ },
+ isNavHeader: function(){
+ // summary:
+ // Overwritten
+ // Check whether currently navigating among column headers.
+ // return:
+ // true - focus is on a certain column header | false otherwise
+ return this._areaQueue[this._currentAreaIdx] == "header";
+ },
+ previousKey: function(e){
+ // summary:
+ // Overwritten
+ this.tab(-1,e);
+ },
+ nextKey: function(e){
+ // summary:
+ // Overwritten
+ this.tab(1,e);
+ },
+ setFocusCell: function(/* Object */inCell, /* Integer */inRowIndex){
+ // summary:
+ // Overwritten - focuses the given grid cell
+ if(inCell){
+ this.currentArea(this.grid.edit.isEditing() ? "editableCell" : "content", true);
+ //This is very slow when selecting cells!
+ //this.focusGridView();
+ this._focusifyCellNode(false);
+ this.cell = inCell;
+ this.rowIndex = inRowIndex;
+ this._focusifyCellNode(true);
+ }
+ this.grid.onCellFocus(this.cell, this.rowIndex);
+ },
+ doFocus: function(e){
+ // summary:
+ // Overwritten
+ // trap focus only for grid dom node
+ // do not focus for scrolling if grid is about to blur
+ if(e && e.target == e.currentTarget && !this.tabbingOut){
+ if(this._gridBlured){
+ this._gridBlured = false;
+ if(this._currentAreaIdx < 0 || this._currentAreaIdx >= this._areaQueue.length){
+ this.focusArea(0, e);
+ }else{
+ this.focusArea(this._currentAreaIdx, e);
+ }
+ }
+ }else{
+ this.tabbingOut = false;
+ }
+ event.stop(e);
+ },
+ _doBlur: function(){
+ this._gridBlured = true;
+ },
+ doLastNodeFocus: function(e){
+ // summary:
+ // Overwritten
+ if(this.tabbingOut){
+ this.tabbingOut = false;
+ }else{
+ this.focusArea(-1, e);
+ }
+ },
+ _delayedHeaderFocus: function(){
+ // summary:
+ // Overwritten
+ if(this.isNavHeader()){
+ this.focusHeader();
+ }
+ },
+ _delayedCellFocus: function(){
+ // summary:
+ // Overwritten
+ this.currentArea("header", true);
+ this.focusArea(this._currentAreaIdx);
+ },
+ _changeMenuBindNode: function(oldBindNode, newBindNode){
+ var hm = this.grid.headerMenu;
+ if(hm && this._contextMenuBindNode == oldBindNode){
+ hm.unBindDomNode(oldBindNode);
+ hm.bindDomNode(newBindNode);
+ this._contextMenuBindNode = newBindNode;
+ }
+ },
+ //---------------Header Area------------------------------------------
+ focusHeader: function(evt, step){ //need a further look why these changes to parent's
+ // summary:
+ // Overwritten
+ var didFocus = false;
+ this.inherited(arguments);
+ if(this._colHeadNode && html.style(this._colHeadNode, 'display') != "none"){
+ dijitFocus.focus(this._colHeadNode);
+ this._stopEvent(evt);
+ didFocus = true;
+ }
+ return didFocus;
+ },
+ _blurHeader: function(evt,step){
+ // summary:
+ // Overwritten
+ if(this._colHeadNode){
+ html.removeClass(this._colHeadNode, this.focusClass);
+ }
+ html.removeAttr(this.grid.domNode,"aria-activedescendant");
+ // reset contextMenu onto viewsHeaderNode so right mouse on header will invoke (see focusHeader)
+ this._changeMenuBindNode(this.grid.domNode,this.grid.viewsHeaderNode);
+ //moved here from nextKey
+ this._colHeadNode = this._colHeadFocusIdx = null;
+ return true;
+ },
+ _navHeader: function(rowStep, colStep, evt){
+ var colDir = colStep < 0 ? -1 : 1,
+ savedIdx = array.indexOf(this._findHeaderCells(), this._colHeadNode);
+ if(savedIdx >= 0 && (evt.shiftKey && evt.ctrlKey)){
+ this.colSizeAdjust(evt, savedIdx, colDir * 5);
+ return;
+ }
+ this.move(rowStep, colStep);
+ },
+ _onHeaderKeyDown: function(e, isBubble){
+ if(isBubble){
+ var dk = keys;
+ switch(e.keyCode){
+ case dk.ENTER:
+ case dk.SPACE:
+ var colIdx = this.getHeaderIndex();
+ if(colIdx >= 0 && !this.grid.pluginMgr.isFixedCell(e.cell)/*TODO*/){
+ this.grid.setSortIndex(colIdx, null, e);
+ event.stop(e);
+ }
+ break;
+ }
+ }
+ return true;
+ },
+ _setActiveColHeader: function(){
+ // summary:
+ // Overwritten
+ this.inherited(arguments);
+ //EDG now will decorate event on header key events, if no focus, the cell will be wrong
+ dijitFocus.focus(this._colHeadNode);
+ },
+ //---------------Content Area------------------------------------------
+ findAndFocusGridCell: function(){
+ // summary:
+ // Overwritten
+ this._focusContent();
+ },
+ _focusContent: function(evt,step){
+ var didFocus = true;
+ var isEmpty = (this.grid.rowCount === 0); // If grid is empty this.grid.rowCount == 0
+ if(this.isNoFocusCell() && !isEmpty){
+ //skip all the hidden cells
+ for(var i = 0, cell = this.grid.getCell(0); cell && cell.hidden; cell = this.grid.getCell(++i)){}
+ this.setFocusIndex(0, cell ? i : 0);
+ }else if(this.cell && !isEmpty){
+ if(this.focusView && !this.focusView.rowNodes[this.rowIndex]){
+ // if rowNode for current index is undefined (likely as a result of a sort and because of #7304)
+ // scroll to that row
+ this.grid.scrollToRow(this.rowIndex);
+ this.focusGrid();
+ }else{
+ this.setFocusIndex(this.rowIndex, this.cell.index);
+ }
+ }else{
+ didFocus = false;
+ }
+ if(didFocus){ this._stopEvent(evt); }
+ return didFocus;
+ },
+ _blurContent: function(evt,step){
+ this._focusifyCellNode(false);
+ return true;
+ },
+ _navContent: function(rowStep, colStep, evt){
+ if((this.rowIndex === 0 && rowStep < 0) || (this.rowIndex === this.grid.rowCount - 1 && rowStep > 0)){
+ return;
+ }
+ this._colHeadNode = null;
+ this.move(rowStep, colStep, evt);
+ if(evt){
+ event.stop(evt);
+ }
+ },
+ _onContentKeyDown: function(e, isBubble){
+ if(isBubble){
+ var dk = keys, s = this.grid.scroller;
+ switch(e.keyCode){
+ case dk.ENTER:
+ case dk.SPACE:
+ var g = this.grid;
+ if(g.indirectSelection){ break; }
+ g.selection.clickSelect(this.rowIndex, connect.isCopyKey(e), e.shiftKey);
+ g.onRowClick(e);
+ event.stop(e);
+ break;
+ case dk.PAGE_UP:
+ if(this.rowIndex !== 0){
+ if(this.rowIndex != s.firstVisibleRow + 1){
+ this._navContent(s.firstVisibleRow - this.rowIndex, 0);
+ }else{
+ this.grid.setScrollTop(s.findScrollTop(this.rowIndex - 1));
+ this._navContent(s.firstVisibleRow - s.lastVisibleRow + 1, 0);
+ }
+ event.stop(e);
+ }
+ break;
+ case dk.PAGE_DOWN:
+ if(this.rowIndex + 1 != this.grid.rowCount){
+ event.stop(e);
+ if(this.rowIndex != s.lastVisibleRow - 1){
+ this._navContent(s.lastVisibleRow - this.rowIndex - 1, 0);
+ }else{
+ this.grid.setScrollTop(s.findScrollTop(this.rowIndex + 1));
+ this._navContent(s.lastVisibleRow - s.firstVisibleRow - 1, 0);
+ }
+ event.stop(e);
+ }
+ break;
+ }
+ }
+ return true;
+ },
+ //------------------editable content area-------------------------
+ _blurFromEditableCell: false,
+ _isNavigating: false,
+ _navElems: null,
+ _focusEditableCell: function(evt,step){
+ var didFocus = false;
+ if(this._isNavigating){
+ didFocus = true;
+ }else if(this.grid.edit.isEditing() && this.cell){
+ if(this._blurFromEditableCell || !this._blurEditableCell(evt, step)){
+ this.setFocusIndex(this.rowIndex,this.cell.index);
+ didFocus = true;
+ }
+ this._stopEvent(evt);
+ }
+ return didFocus;
+ },
+ _applyEditableCell: function(){
+ try{
+ this.grid.edit.apply();
+ }catch(e){
+ console.warn("_FocusManager._applyEditableCell() error:", e);
+ }
+ },
+ _blurEditableCell: function(evt,step){
+ this._blurFromEditableCell = false;
+ if(this._isNavigating){
+ var toBlur = true;
+ if(evt){
+ var elems = this._navElems;
+ var firstElem = elems.lowest || elems.first;
+ var lastElem = elems.last || elems.highest || firstElem;
+ var target = has("ie") ? evt.srcElement : evt.target;
+ toBlur = target == (step > 0 ? lastElem : firstElem);
+ }
+ if(toBlur){
+ this._isNavigating = false;
+ html.setSelectable(this.cell.getNode(this.rowIndex), false);
+ return "content";
+ }
+ return false;
+ }else if(this.grid.edit.isEditing() && this.cell){
+ if(!step || typeof step != "number"){ return false; }
+ var dir = step > 0 ? 1 : -1;
+ var cc = this.grid.layout.cellCount;
+ for(var cell, col = this.cell.index + dir; col >= 0 && col < cc; col += dir){
+ cell = this.grid.getCell(col);
+ if(cell.editable){
+ this.cell = cell;
+ this._blurFromEditableCell = true;
+ return false;
+ }
+ }
+ if((this.rowIndex > 0 || dir == 1) && (this.rowIndex < this.grid.rowCount || dir == -1)){
+ this.rowIndex += dir;
+ //this.cell = this.grid.getCell(0); //There must be an editable cell, so this is not necessary.
+ for(col = dir > 0 ? 0 : cc - 1; col >= 0 && col < cc; col += dir){
+ cell = this.grid.getCell(col);
+ if(cell.editable){
+ this.cell = cell;
+ break;
+ }
+ }
+ this._applyEditableCell();
+ return "content";
+ }
+ }
+ return true;
+ },
+ _initNavigatableElems: function(){
+ this._navElems = dijitA11y._getTabNavigable(this.cell.getNode(this.rowIndex));
+ },
+ _onEditableCellKeyDown: function(e, isBubble){
+ var dk = keys,
+ g = this.grid,
+ edit = g.edit,
+ editApplied = false,
+ toPropagate = true;
+ switch(e.keyCode){
+ case dk.ENTER:
+ if(isBubble && edit.isEditing()){
+ this._applyEditableCell();
+ editApplied = true;
+ event.stop(e);
+ }
+ //intentional drop through
+ case dk.SPACE:
+ if(!isBubble && this._isNavigating){
+ toPropagate = false;
+ break;
+ }
+ if(isBubble){
+ if(!this.cell.editable && this.cell.navigatable){
+ this._initNavigatableElems();
+ var toFocus = this._navElems.lowest || this._navElems.first;
+ if(toFocus){
+ this._isNavigating = true;
+ html.setSelectable(this.cell.getNode(this.rowIndex), true);
+ dijitFocus.focus(toFocus);
+ event.stop(e);
+ this.currentArea("editableCell", true);
+ break;
+ }
+ }
+ if(!editApplied && !edit.isEditing() && !g.pluginMgr.isFixedCell(this.cell)){
+ edit.setEditCell(this.cell, this.rowIndex);
+ }
+ if(editApplied){
+ this.currentArea("content", true);
+ }else if(this.cell.editable && g.canEdit()){
+ this.currentArea("editableCell", true);
+ }
+ }
+ break;
+ case dk.PAGE_UP:
+ case dk.PAGE_DOWN:
+ if(!isBubble && edit.isEditing()){
+ //prevent propagating to content area
+ toPropagate = false;
+ }
+ break;
+ case dk.ESCAPE:
+ if(!isBubble){
+ edit.cancel();
+ this.currentArea("content", true);
+ }
+ }
+ return toPropagate;
+ },
+ _onEditableCellMouseEvent: function(evt){
+ if(evt.type == "click"){
+ var cell = this.cell || evt.cell;
+ if(cell && !cell.editable && cell.navigatable){
+ this._initNavigatableElems();
+ if(this._navElems.lowest || this._navElems.first){
+ var target = has("ie") ? evt.srcElement : evt.target;
+ if(target != cell.getNode(evt.rowIndex)){
+ this._isNavigating = true;
+ this.focusArea("editableCell", evt);
+ html.setSelectable(cell.getNode(evt.rowIndex), true);
+ dijitFocus.focus(target);
+ return false;
+ }
+ }
+ }else if(this.grid.singleClickEdit){
+ this.currentArea("editableCell");
+ return false;
+ }
+ }
+ return true;
+ }
+});
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/_Plugin.js b/js/dojo/dojox/grid/enhanced/_Plugin.js
new file mode 100644
index 0000000..b0a4969
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/_Plugin.js
@@ -0,0 +1,172 @@
+//>>built
+define("dojox/grid/enhanced/_Plugin", [
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "../EnhancedGrid"
+], function(dojo, lang, declare, array, connect){
+
+return declare("dojox.grid.enhanced._Plugin", null, {
+ // summary:
+ // Base class for all plugins.
+ //
+ // description:
+ // Provides common plugin functionality and basic life cycle management.
+ //
+ // Each concrete plugin must have a name field and is responsible for registering itself to the global plugin registry
+ // e.g. for dnd plugin:
+ // | dojox.grid.EnhancedGrid.registerPlugin("dnd" /*plugin name*/,
+ // | dojox.grid.enhanced.plugins.DnD /*full class name of a plugin*/
+ // | {"preInit": false, "dependency": ["nestedSorting"]} /*properties*/);
+ //
+ // [Keywords] of plugin properties(case sensitive)
+ // - "preInit": boolean, whether a plugin should be created before EnhancedGrid.postCreate(),
+ // false by default(plugins are created after EnhancedGrid.postCreate()).
+ // - "dependency": array or string, plugin(s) indicated by "dependency" will be created before the current one.
+ // Note: recursive cycle dependencies are not supported e.g. following dependency is invalid:
+ // pluginA -> pluginB -> pluginA
+ //
+ // example:
+ // 1. Customize default DnD plugin
+ // | dojo.declare("mygrid.MyDnD", dojox.grid.enhanced.plugins.DnD, {
+ // | name:"dnd" //still reuse the plugin name
+ // | constructor: function(inGrid, option){ ... }
+ // | });
+ // | dojox.grid.EnhancedGrid.registerPlugin("dnd", mygrid.MyDnD);
+ //
+ // 2. Add new plugin - PluginA
+ // | dojo.declare("mygrid.PluginA", dojox.grid.enhanced._Plugin, {
+ // | name: "pA",
+ // | constructor: function(inGrid, option){ ... }
+ // | });
+ // | dojox.grid.EnhancedGrid.registerPlugin("pA",mygrid.PluginA);
+ //
+ // 3. Use plugins
+ // | dojo.require("mygrid.MyDnD");
+ // | dojo.require("mygrid.PluginA");
+
+ // | <script type="text/javascript">
+ // | var grid = new dojox.grid.EnhancedGrid(
+ // | {plugins: {dnd:true, pA:true}, ... }, dojo.byId("gridDiv"));
+ // | grid.startup();
+ // | </script>
+
+ //name: String
+ // Plugin name, e.g. 'nestedSorting', 'dnd'...
+ name: 'plugin',
+
+ //grid: Object
+ // Grid that the plugin belongs to
+ grid: null,
+
+ //option: Object
+ // Plugin properties - leveraged with default and user specified properties.
+ // e.g. for dnd plugin, it may look like {"class": dojox.grid.enhanced.plugins.DnD, "dependency": ["nestedSorting"], ...}
+ option: {},
+
+ //_connects: Array
+ // List of all connections.
+ _connects: [],
+
+ //_subscribes: Array
+ // List of all subscribes.
+ _subscribes: [],
+
+ //privates: Object
+ // Private properties/methods shouldn't be mixin-ed anytime.
+ privates: {},
+
+ constructor: function(inGrid, option){
+ this.grid = inGrid;
+ this.option = option;
+ this._connects = [];
+ this._subscribes = [];
+ this.privates = lang.mixin({},dojox.grid.enhanced._Plugin.prototype);
+ this.init();
+ },
+
+ init: function(){},
+
+ onPreInit: function(){},
+
+ onPostInit: function(){},
+
+ onStartUp: function(){},
+
+ connect: function(obj, event, method){
+ // summary:
+ // Connects specified obj/event to specified method of this object.
+ // example:
+ // | var plugin = new dojox.grid.enhanced._Plugin(grid,"myPlugin",{...});
+ // | // when foo.bar() is called, call the listener in the scope of plugin
+ // | plugin.connect(foo, "bar", function(){
+ // | console.debug(this.xxx());//"this" - plugin scope
+ // | });
+ var conn = connect.connect(obj, event, this, method);
+ this._connects.push(conn);
+ return conn;
+ },
+ disconnect: function(handle){
+ // summary:
+ // Disconnects handle and removes it from connection list.
+ array.some(this._connects, function(conn, i, conns){
+ if(conn == handle){
+ connect.disconnect(handle);
+ conns.splice(i, 1);
+ return true;
+ }
+ return false;
+ });
+ },
+ subscribe: function(topic, method){
+ // summary:
+ // Subscribes to the specified topic and calls the specified method
+ // of this object.
+ // example:
+ // | var plugin = new dojox.grid.enhanced._Plugin(grid,"myPlugin",{...});
+ // | // when /my/topic is published, call the subscriber in the scope of plugin
+ // | // with passed parameter - "v"
+ // | plugin.subscribe("/my/topic", function(v){
+ // | console.debug(this.xxx(v));//"this" - plugin scope
+ // | });
+ var subscribe = connect.subscribe(topic, this, method);
+ this._subscribes.push(subscribe);
+ return subscribe;
+ },
+ unsubscribe: function(handle){
+ // summary:
+ // Un-subscribes handle and removes it from subscriptions list.
+ array.some(this._subscribes, function(subscribe, i, subscribes){
+ if(subscribe == handle){
+ connect.unsubscribe(handle);
+ subscribes.splice(i, 1);
+ return true;
+ }
+ return false;
+ });
+ },
+ onSetStore: function(store){
+ // summary:
+ // Called when store is changed.
+ },
+ destroy: function(){
+ // summary:
+ // Destroy all resources.
+ array.forEach(this._connects, connect.disconnect);
+ array.forEach(this._subscribes, connect.unsubscribe);
+ delete this._connects;
+ delete this._subscribes;
+ delete this.option;
+ delete this.privates;
+ //console.log('Plugin [', this.name, '].destroy() executed!');
+ }
+});
+
+//Each plugin is responsible for registering itself
+// e.g. for DnD plugin(name:'dnd'):
+// | dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.DnD/*class*/,
+// | {"dependency": ["nestedSorting"]}/*Optional - properties*/);
+
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/_PluginManager.js b/js/dojo/dojox/grid/enhanced/_PluginManager.js
new file mode 100644
index 0000000..20e6e91
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/_PluginManager.js
@@ -0,0 +1,275 @@
+//>>built
+define("dojox/grid/enhanced/_PluginManager", [
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "./_Events",
+ "./_FocusManager",
+ "../util"
+], function(dojo, lang, declare, array, connect, _Events, _FocusManager, util){
+
+var _PluginManager = declare("dojox.grid.enhanced._PluginManager", null, {
+ // summary:
+ // Singleton plugin manager
+ //
+ // description:
+ // Plugin manager is responsible for
+ // 1. Loading required plugins
+ // 2. Handling collaborat ion and dependencies among plugins
+ //
+ // Some plugin dependencies:
+ // - "columnReordering" attribute won't work when either DnD or Indirect Selections plugin is on.
+
+ //_options: Object
+ // Normalized plugin options
+ _options: null,
+
+ //_plugins: Array
+ // Plugin list
+ _plugins: null,
+
+ //_connects: Array
+ // Connection list
+ _connects: null,
+
+ constructor: function(inGrid){
+ this.grid = inGrid;
+ this._store = inGrid.store;
+ this._options = {};
+ this._plugins = [];
+ this._connects = [];
+ this._parseProps(this.grid.plugins);
+
+ inGrid.connect(inGrid, "_setStore", lang.hitch(this, function(store){
+ if(this._store !== store){
+ this.forEach('onSetStore', [store, this._store]);
+ this._store = store;
+ }
+ }));
+ },
+ startup: function(){
+ this.forEach('onStartUp');
+ },
+ preInit: function(){
+ // summary:
+ // Load appropriate plugins before DataGrid.postCreate().
+ // See EnhancedGrid.postCreate()
+ this.grid.focus.destroy();
+ this.grid.focus = new _FocusManager(this.grid);
+ new _Events(this.grid);//overwrite some default events of DataGrid
+ this._init(true);
+ this.forEach('onPreInit');
+ },
+ postInit: function(){
+ // summary:
+ // Load plugins after DataGrid.postCreate() - the default phase when plugins are created
+ // See EnhancedGrid.postCreate()
+ this._init(false);
+
+ array.forEach(this.grid.views.views, this._initView, this);
+ this._connects.push(connect.connect(this.grid.views, 'addView', lang.hitch(this, this._initView)));
+
+ if(this._plugins.length > 0){
+ var edit = this.grid.edit;
+ if(edit){ edit.styleRow = function(inRow){}; }
+ }
+ this.forEach('onPostInit');
+ },
+ forEach: function(func, args){
+ array.forEach(this._plugins, function(p){
+ if(!p || !p[func]){ return; }
+ p[func].apply(p, args ? args : []);
+ });
+ },
+ _parseProps: function(plugins){
+ // summary:
+ // Parse plugins properties
+ // plugins: Object
+ // Plugin properties defined by user
+ if(!plugins){ return; }
+
+ var p, loading = {}, options = this._options, grid = this.grid;
+ var registry = _PluginManager.registry;//global plugin registry
+ for(p in plugins){
+ if(plugins[p]){//filter out boolean false e.g. {p:false}
+ this._normalize(p, plugins, registry, loading);
+ }
+ }
+ //"columnReordering" attribute won't work when either DnD or Indirect Selections plugin is used.
+ if(options.dnd || options.indirectSelection){
+ options.columnReordering = false;
+ }
+
+ //mixin all plugin properties into Grid
+ lang.mixin(grid, options);
+ },
+ _normalize: function(p, plugins, registry, loading){
+ // summary:
+ // Normalize plugin properties especially the dependency chain
+ // p: String
+ // Plugin name
+ // plugins: Object
+ // Plugin properties set by user
+ // registry: Object
+ // The global plugin registry
+ // loading: Object
+ // Map for checking process state
+ if(!registry[p]){ throw new Error('Plugin ' + p + ' is required.');}
+
+ if(loading[p]){ throw new Error('Recursive cycle dependency is not supported.'); }
+
+ var options = this._options;
+ if(options[p]){ return options[p]; }
+
+ loading[p] = true;
+ //TBD - more strict conditions?
+ options[p] = lang.mixin({}, registry[p], lang.isObject(plugins[p]) ? plugins[p] : {});
+
+ var dependencies = options[p]['dependency'];
+ if(dependencies){
+ if(!lang.isArray(dependencies)){
+ dependencies = options[p]['dependency'] = [dependencies];
+ }
+ array.forEach(dependencies, function(dependency){
+ if(!this._normalize(dependency, plugins, registry, loading)){
+ throw new Error('Plugin ' + dependency + ' is required.');
+ }
+ }, this);
+ }
+ delete loading[p];
+ return options[p];
+ },
+ _init: function(pre){
+ // summary:
+ // Find appropriate plugins and load them
+ // pre: Boolean
+ // True - preInit | False - postInit(by default)
+ var p, preInit, options = this._options;
+ for(p in options){
+ preInit = options[p]['preInit'];
+ if((pre ? preInit : !preInit) && options[p]['class'] && !this.pluginExisted(p)){
+ this.loadPlugin(p);
+ }
+ }
+ },
+ loadPlugin: function(name){
+ // summary:
+ // Load required plugin("name")
+ // name: String
+ // Plugin name
+ // return: Object
+ // The newly loaded plugin
+ var option = this._options[name];
+ if(!option){ return null; } //return if no plugin option
+
+ var plugin = this.getPlugin(name);
+ if(plugin){ return plugin; } //return if plugin("name") already existed
+
+ var dependencies = option['dependency'];
+ array.forEach(dependencies, function(dependency){
+ if(!this.loadPlugin(dependency)){
+ throw new Error('Plugin ' + dependency + ' is required.');
+ }
+ }, this);
+ var cls = option['class'];
+ delete option['class'];//remove it for safety
+ plugin = new this.getPluginClazz(cls)(this.grid, option);
+ this._plugins.push(plugin);
+ return plugin;
+ },
+ _initView: function(view){
+ // summary:
+ // Overwrite several default behavior for each views(including _RowSelector view)
+ if(!view){ return; }
+ //add more events handler - _View
+ util.funnelEvents(view.contentNode, view, "doContentEvent", ['mouseup', 'mousemove']);
+ util.funnelEvents(view.headerNode, view, "doHeaderEvent", ['mouseup']);
+ },
+ pluginExisted: function(name){
+ // summary:
+ // Check if plugin("name") existed
+ // name: String
+ // Plugin name
+ // return: Boolean
+ // True - existed | False - not existed
+ return !!this.getPlugin(name);
+ },
+ getPlugin: function(name){
+ // summary:
+ // Get plugin("name")
+ // name: String
+ // Plugin name
+ // return: Object
+ // Plugin instance
+ var plugins = this._plugins;
+ name = name.toLowerCase();
+ for(var i = 0, len = plugins.length; i < len; i++){
+ if(name == plugins[i]['name'].toLowerCase()){
+ return plugins[i];
+ }
+ }
+ return null;
+ },
+ getPluginClazz: function(clazz){
+ // summary:
+ // Load target plugin which must be already required (require(..))
+ // clazz: class | String
+ // Plugin class
+ if(lang.isFunction(clazz)){
+ return clazz;//return if it's already a clazz
+ }
+ var errorMsg = 'Please make sure Plugin "' + clazz + '" is existed.';
+ try{
+ var cls = lang.getObject(clazz);
+ if(!cls){ throw new Error(errorMsg); }
+ return cls;
+ }catch(e){
+ throw new Error(errorMsg);
+ }
+ },
+ isFixedCell: function(cell){
+ // summary:
+ // See if target cell(column) is fixed or not.
+ // cell: Object
+ // Target cell(column)
+ // return: Boolean
+ // True - fixed| False - not fixed
+
+ //target cell can use Boolean attributes named "isRowSelector" or "fixedPos" to mark it's a fixed cell(column)
+ return cell && (cell.isRowSelector || cell.fixedPos);
+ },
+ destroy: function(){
+ // summary:
+ // Destroy all resources
+ array.forEach(this._connects, connect.disconnect);
+ this.forEach('destroy');
+ if(this.grid.unwrap){
+ this.grid.unwrap();
+ }
+ delete this._connects;
+ delete this._plugins;
+ delete this._options;
+ }
+});
+
+_PluginManager.registerPlugin = function(clazz, props){
+ // summary:
+ // Register plugins - TODO, a better way rather than global registry?
+ // clazz: String
+ // Full class name, e.g. "dojox.grid.enhanced.plugins.DnD"
+ // props: Object - Optional
+ // Plugin properties e.g. {"dependency": ["nestedSorting"], ...}
+ if(!clazz){
+ console.warn("Failed to register plugin, class missed!");
+ return;
+ }
+ var cls = _PluginManager;
+ cls.registry = cls.registry || {};
+ cls.registry[clazz.prototype.name]/*plugin name*/ = lang.mixin({"class": clazz}, (props ? props : {}));
+};
+
+return _PluginManager;
+
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/nls/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/EnhancedGrid.js
new file mode 100644
index 0000000..29bd64b
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/EnhancedGrid.js
@@ -0,0 +1,48 @@
+//>>built
+define("dojox/grid/enhanced/nls/EnhancedGrid", { root:
+//begin v1.x content
+({
+ singleSort: "Single Sort",
+ nestedSort: "Nested Sort",
+ ascending: "Click to sort Ascending",
+ descending: "Click to sort Descending",
+ sortingState: "${0} - ${1}",
+ unsorted: "Do not sort this column",
+ indirectSelectionRadio: "Row ${0}, single selection, radio box",
+ indirectSelectionCheckBox: "Row ${0}, multiple selection, check box",
+ selectAll: "Select all"
+})
+//end v1.x content
+,
+"ar": true,
+"ca": true,
+"cs": true,
+"da": true,
+"de": true,
+"el": true,
+"es": true,
+"fi": true,
+"fr": true,
+"he": true,
+"hr": true,
+"hu": true,
+"hr": true,
+"it": true,
+"ja": true,
+"kk": true,
+"ko": true,
+"nb": true,
+"nl": true,
+"pl": true,
+"pt": true,
+"pt-pt": true,
+"ro": true,
+"ru": true,
+"sk": true,
+"sl": true,
+"sv": true,
+"th": true,
+"tr": true,
+"zh": true,
+"zh-tw": true
+});
diff --git a/js/dojo/dojox/grid/enhanced/nls/Filter.js b/js/dojo/dojox/grid/enhanced/nls/Filter.js
new file mode 100644
index 0000000..5bf56a4
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/Filter.js
@@ -0,0 +1,121 @@
+//>>built
+define("dojox/grid/enhanced/nls/Filter", { root:
+//begin v1.x content
+({
+ "clearFilterDialogTitle": "Clear Filter",
+ "filterDefDialogTitle": "Filter",
+ "ruleTitleTemplate": "Rule ${0}",
+
+ "conditionEqual": "equal",
+ "conditionNotEqual": "does not equal",
+ "conditionLess": "is less than",
+ "conditionLessEqual": "less than or equal",
+ "conditionLarger": "is greater than",
+ "conditionLargerEqual": "greater than or equal",
+ "conditionContains": "contains",
+ "conditionIs": "is",
+ "conditionStartsWith": "starts with",
+ "conditionEndWith": "ends with",
+ "conditionNotContain": "does not contain",
+ "conditionIsNot": "is not",
+ "conditionNotStartWith": "does not start with",
+ "conditionNotEndWith": "does not end with",
+ "conditionBefore": "before",
+ "conditionAfter": "after",
+ "conditionRange": "range",
+ "conditionIsEmpty": "is empty",
+
+ "all": "all",
+ "any": "any",
+ "relationAll": "all rules",
+ "waiRelAll": "Match all of the following rules:",
+ "relationAny": "any rules",
+ "waiRelAny": "Match any of the following rules:",
+ "relationMsgFront": "Match:",
+ "relationMsgTail": "",
+ "and": "and",
+ "or": "or",
+
+ "addRuleButton": "Add Rule",
+ "waiAddRuleButton": "Add a new rule",
+ "removeRuleButton": "Remove Rule",
+ "waiRemoveRuleButtonTemplate": "Remove rule ${0}",
+
+ "cancelButton": "Cancel",
+ "waiCancelButton": "Cancel this dialog",
+ "clearButton": "Clear",
+ "waiClearButton": "Clear the filter",
+ "filterButton": "Filter",
+ "waiFilterButton": "Submit the filter",
+
+ "columnSelectLabel": "Column",
+ "waiColumnSelectTemplate": "Column for rule ${0}",
+ "conditionSelectLabel": "Condition",
+ "waiConditionSelectTemplate": "Condition for rule ${0}",
+ "valueBoxLabel": "Value",
+ "waiValueBoxTemplate": "Enter value to filter for rule ${0}",
+
+ "rangeTo": "to",
+ "rangeTemplate": "from ${0} to ${1}",
+
+ "statusTipHeaderColumn": "Column",
+ "statusTipHeaderCondition": "Rules",
+ "statusTipTitle": "Filter Bar",
+ "statusTipMsg": "Click the filter bar here to filter on values in ${0}.",
+ "anycolumn": "any column",
+ "statusTipTitleNoFilter": "Filter Bar",
+ "statusTipTitleHasFilter": "Filter",
+ "statusTipRelAny": "Match any rules.",
+ "statusTipRelAll": "Match all rules.",
+
+ "defaultItemsName": "items",
+ "filterBarMsgHasFilterTemplate": "${0} of ${1} ${2} shown.",
+ "filterBarMsgNoFilterTemplate": "No filter applied",
+
+ "filterBarDefButton": "Define filter",
+ "waiFilterBarDefButton": "Filter the table",
+ "a11yFilterBarDefButton": "Filter...",
+ "filterBarClearButton": "Clear filter",
+ "waiFilterBarClearButton": "Clear the filter",
+ "closeFilterBarBtn": "Close filter bar",
+
+ "clearFilterMsg": "This will remove the filter and show all available records.",
+ "anyColumnOption": "Any Column",
+
+ "trueLabel": "True",
+ "falseLabel": "False"
+})
+//end v1.x content
+,
+"ar": true,
+"ca": true,
+"cs": true,
+"da": true,
+"de": true,
+"el": true,
+"es": true,
+"fi": true,
+"fr": true,
+"he": true,
+"hr": true,
+"hu": true,
+"hr": true,
+"it": true,
+"ja": true,
+"kk": true,
+"ko": true,
+"nb": true,
+"nl": true,
+"pl": true,
+"pt": true,
+"pt-pt": true,
+"ro": true,
+"ru": true,
+"sk": true,
+"sl": true,
+"sv": true,
+"th": true,
+"tr": true,
+"zh": true,
+"zh-tw": true
+});
diff --git a/js/dojo/dojox/grid/enhanced/nls/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/Pagination.js
new file mode 100644
index 0000000..65eec33
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/Pagination.js
@@ -0,0 +1,56 @@
+//>>built
+define("dojox/grid/enhanced/nls/Pagination", { root:
+//begin v1.x content
+({
+ "descTemplate": "${2} - ${3} of ${1} ${0}",
+ "firstTip": "First Page",
+ "lastTip": "Last Page",
+ "nextTip": "Next Page",
+ "prevTip": "Previous Page",
+ "itemTitle": "items",
+ "singularItemTitle": "item",
+ "pageStepLabelTemplate": "Page ${0}",
+ "pageSizeLabelTemplate": "${0} items per page",
+ "allItemsLabelTemplate": "All items",
+ "gotoButtonTitle": "Go to a specific page",
+ "dialogTitle": "Go to Page",
+ "dialogIndication": "Specify the page number",
+ "pageCountIndication": " (${0} pages)",
+ "dialogConfirm": "Go",
+ "dialogCancel": "Cancel",
+ "all": "All"
+})
+//end v1.x content
+,
+"ar": true,
+"ca": true,
+"cs": true,
+"da": true,
+"de": true,
+"el": true,
+"es": true,
+"fi": true,
+"fr": true,
+"he": true,
+"hr": true,
+"hu": true,
+"hr": true,
+"it": true,
+"ja": true,
+"kk": true,
+"ko": true,
+"nb": true,
+"nl": true,
+"pl": true,
+"pt": true,
+"pt-pt": true,
+"ro": true,
+"ru": true,
+"sk": true,
+"sl": true,
+"sv": true,
+"th": true,
+"tr": true,
+"zh": true,
+"zh-tw": true
+});
diff --git a/js/dojo/dojox/grid/enhanced/nls/ar/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/ar/EnhancedGrid.js
new file mode 100644
index 0000000..f55709f
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ar/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ar/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "فرز منفرد",
+ nestedSort: "فرز متداخل",
+ ascending: "تصاعدي",
+ descending: "تنازلي",
+ sortingState: "${0} - ${1}",
+ unsorted: "عدم فرز هذا العمود",
+ indirectSelectionRadio: "الصف ${0}، اختيار منفرد، اختيار دائري",
+ indirectSelectionCheckBox: "الصف ${0}، اختيارات متعددة، مربع اختيار",
+ selectAll: "تحديد كل"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/ar/Filter.js b/js/dojo/dojox/grid/enhanced/nls/ar/Filter.js
new file mode 100644
index 0000000..fa26b93
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ar/Filter.js
@@ -0,0 +1,90 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ar/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "محو ترشيح البيانات",
+ "filterDefDialogTitle": "ترشيح البيانات",
+ "ruleTitleTemplate": "القاعدة ${0}",
+
+ "conditionEqual": "يساوي",
+ "conditionNotEqual": "لا يساوي",
+ "conditionLess": "أصغر من",
+ "conditionLessEqual": "أصغر من أو يساوي",
+ "conditionLarger": "أكبر من",
+ "conditionLargerEqual": "أكبر من أو يساوي",
+ "conditionContains": "يتضمن",
+ "conditionIs": "هو",
+ "conditionStartsWith": "يبدأ بالحروف",
+ "conditionEndWith": "ينتهي بالحروف",
+ "conditionNotContain": "لا يتضمن",
+ "conditionIsNot": "ليس",
+ "conditionNotStartWith": "لا يبدأ بالحروف",
+ "conditionNotEndWith": "لا ينتهي بالحروف",
+ "conditionBefore": "قبل",
+ "conditionAfter": "بعد",
+ "conditionRange": "المدى",
+ "conditionIsEmpty": "خالي",
+
+ "all": "كل",
+ "any": "أي",
+ "relationAll": "كل القواعد",
+ "waiRelAll": "مطابقة كل القواعد التالية:",
+ "relationAny": "أية قواعد",
+ "waiRelAny": "مطابقة أي من القواعد التالية:",
+ "relationMsgFront": "مطابقة",
+ "relationMsgTail": "",
+ "and": "and",
+ "or": "or",
+
+ "addRuleButton": "اضافة قاعدة",
+ "waiAddRuleButton": "اضافة قاعدة جديدة",
+ "removeRuleButton": "ازالة قاعدة",
+ "waiRemoveRuleButtonTemplate": "ازالة القاعدة ${0}",
+
+ "cancelButton": "الغاء",
+ "waiCancelButton": "الغاء مربع الحوار هذا",
+ "clearButton": "محو",
+ "waiClearButton": "محو ترشيح البيانات",
+ "filterButton": "ترشيح البيانات",
+ "waiFilterButton": "احالة ترشيح البيانات",
+
+ "columnSelectLabel": "العمود",
+ "waiColumnSelectTemplate": "العمود للقاعدة ${0}",
+ "conditionSelectLabel": "الشرط",
+ "waiConditionSelectTemplate": "الشرط للقاعدة ${0}",
+ "valueBoxLabel": "القيمة",
+ "waiValueBoxTemplate": "أدخل قيمة لترشيح البيانات للقاعدة ${0}",
+
+ "rangeTo": "الى",
+ "rangeTemplate": "من ${0} الى ${1}",
+
+ "statusTipHeaderColumn": "العمود",
+ "statusTipHeaderCondition": "القواعد",
+ "statusTipTitle": "خط ترشيح البيانات",
+ "statusTipMsg": "اضغط على خط ترشيح البيانات هنا لترشيح البيانات بناءا على القيم التي توجد في ${0}.",
+ "anycolumn": "أي عمود",
+ "statusTipTitleNoFilter": "خط ترشيح البيانات",
+ "statusTipTitleHasFilter": "ترشيح البيانات",
+
+ "defaultItemsName": "بنود",
+ "filterBarMsgHasFilterTemplate": "يتم عرض ${0} من ${1} ${2}.",
+ "filterBarMsgNoFilterTemplate": "لم يتم تطبيق أي ترشيح للبيانات.",
+
+ "filterBarDefButton": "تعريف ترشيح البيانات",
+ "waiFilterBarDefButton": "ترشيح بيانات الجدول",
+ "a11yFilterBarDefButton": "ترشيح البيانات...",
+ "filterBarClearButton": "محو ترشيح البيانات",
+ "waiFilterBarClearButton": "محو ترشيح البيانات",
+ "closeFilterBarBtn": "اغلاق خط ترشيح البيانات",
+
+ "clearFilterMsg": "سيؤدي هذا الى ازالة ترشيح البيانات وعرض كل السجلات المتاحة.",
+ "anyColumnOption": "أي عمود",
+
+ "trueLabel": "متحقق",
+ "falseLabel": "غير متحقق"
+})
+//end v1.x content
+);
+
+
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/ar/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/ar/Pagination.js
new file mode 100644
index 0000000..ed7a329
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ar/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ar/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} من ${1} ${0}",
+ "firstTip": "الصفحة الأولى",
+ "lastTip": "الصفحة الأخيرة",
+ "nextTip": "الصفحة التالية",
+ "prevTip": "الصفحة السابقة",
+ "itemTitle": "بنود",
+ "pageStepLabelTemplate": "الصفحة ${0}",
+ "pageSizeLabelTemplate": "${0} بند/بنود بكل صفحة",
+ "allItemsLabelTemplate": "كل البنود",
+ "gotoButtonTitle": "اذهب الى الصفحة المحددة",
+ "dialogTitle": "اذهب الى الصفحة",
+ "dialogIndication": "حدد رقم الصفحة",
+ "pageCountIndication": " (${0} صفحات)",
+ "dialogConfirm": "بدء",
+ "dialogCancel": "الغاء",
+ "all": "كل"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/ca/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/ca/EnhancedGrid.js
new file mode 100644
index 0000000..b5eb2c3
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ca/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ca/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Ordre únic",
+ nestedSort: "Ordre imbricat",
+ ascending: "Ascendent",
+ descending: "Descendent",
+ sortingState: "${0} - ${1}",
+ unsorted: "No ordenis aquesta finestra",
+ indirectSelectionRadio: "Fila ${0}, selecció única, quadre d'opció",
+ indirectSelectionCheckBox: "Fila ${0}, selecció múltiple, quadre de selecció",
+ selectAll: "Seleccionar-ho tot"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/ca/Filter.js b/js/dojo/dojox/grid/enhanced/nls/ca/Filter.js
new file mode 100644
index 0000000..f758b8d
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ca/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ca/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Netejar el filtre",
+ "filterDefDialogTitle": "Filtre",
+ "ruleTitleTemplate": "Regla ${0}",
+
+ "conditionEqual": "igual que",
+ "conditionNotEqual": "no és igual que",
+ "conditionLess": "és menys que",
+ "conditionLessEqual": "és menys o igual que",
+ "conditionLarger": "és més que",
+ "conditionLargerEqual": "és més o igual que",
+ "conditionContains": "conté",
+ "conditionIs": "és",
+ "conditionStartsWith": "comença per",
+ "conditionEndWith": "acaba per",
+ "conditionNotContain": "no conté",
+ "conditionIsNot": "no és",
+ "conditionNotStartWith": "no comença per",
+ "conditionNotEndWith": "no acaba per",
+ "conditionBefore": "abans",
+ "conditionAfter": "després",
+ "conditionRange": "interval",
+ "conditionIsEmpty": "és buida",
+
+ "all": "tot",
+ "any": "qualsevol",
+ "relationAll": "totes les regles",
+ "waiRelAll": "Fes coincidir totes les regles següents:",
+ "relationAny": "qualsevol regla",
+ "waiRelAny": "Fes coincidir qualsevol de les regles següents:",
+ "relationMsgFront": "Coincidència",
+ "relationMsgTail": "",
+ "and": "i",
+ "or": "o",
+
+ "addRuleButton": "Afegeix regla",
+ "waiAddRuleButton": "Afegeix una regla nova",
+ "removeRuleButton": "Elimina regla",
+ "waiRemoveRuleButtonTemplate": "Elimina la regla ${0}",
+
+ "cancelButton": "Cancel·la",
+ "waiCancelButton": "Cancel·la aquest diàleg",
+ "clearButton": "Esborra",
+ "waiClearButton": "Neteja el filtre",
+ "filterButton": "Filtre",
+ "waiFilterButton": "Envia el filtre",
+
+ "columnSelectLabel": "Columna",
+ "waiColumnSelectTemplate": "Columna per a la regla ${0}",
+ "conditionSelectLabel": "Condició",
+ "waiConditionSelectTemplate": "Condició per a la regla ${0}",
+ "valueBoxLabel": "Valor",
+ "waiValueBoxTemplate": "Especifiqueu el valor de filtre per a la regla ${0}",
+
+ "rangeTo": "a",
+ "rangeTemplate": "de ${0} a ${1}",
+
+ "statusTipHeaderColumn": "Columna",
+ "statusTipHeaderCondition": "Regles",
+ "statusTipTitle": "Barra de filtre",
+ "statusTipMsg": "Feu clic aquí a la barra de filtre per filtrar els valors a ${0}.",
+ "anycolumn": "qualsevol columna",
+ "statusTipTitleNoFilter": "Barra de filtre",
+ "statusTipTitleHasFilter": "Filtre",
+ "statusTipRelAny": "Coincideix amb qualsevol regla.",
+ "statusTipRelAll": "Coincideix amb totes les regles.",
+
+ "defaultItemsName": "elements",
+ "filterBarMsgHasFilterTemplate": "Es mostren ${0} de ${1} ${2}.",
+ "filterBarMsgNoFilterTemplate": "No s'ha aplicat cap filtre",
+
+ "filterBarDefButton": "Defineix filtre",
+ "waiFilterBarDefButton": "Filtra la taula",
+ "a11yFilterBarDefButton": "Filtre...",
+ "filterBarClearButton": "Netejar filtre",
+ "waiFilterBarClearButton": "Neteja el filtre",
+ "closeFilterBarBtn": "Tancar la barra de filtre",
+
+ "clearFilterMsg": "Això eliminarà el filtre i mostrarà tots els registres disponibles.",
+ "anyColumnOption": "Qualsevol columna",
+
+ "trueLabel": "Cert",
+ "falseLabel": "Fals"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/ca/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/ca/Pagination.js
new file mode 100644
index 0000000..74b7121
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ca/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ca/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} de ${1} ${0}",
+ "firstTip": "Primera pàgina",
+ "lastTip": "Darrera pàgina",
+ "nextTip": "Pàgina següent",
+ "prevTip": "Pàgina anterior",
+ "itemTitle": "elements",
+ "singularItemTitle": "element",
+ "pageStepLabelTemplate": "Pàgina ${0}",
+ "pageSizeLabelTemplate": "${0} elements per pàgina",
+ "allItemsLabelTemplate": "Tots els elements",
+ "gotoButtonTitle": "Vés a una pàgina específica",
+ "dialogTitle": "Vés a pàgina",
+ "dialogIndication": "Especifiqueu el número de pàgina",
+ "pageCountIndication": " (${0} pàgines)",
+ "dialogConfirm": "Vés-hi",
+ "dialogCancel": "Cancel·la",
+ "all": "tot"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/cs/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/cs/EnhancedGrid.js
new file mode 100644
index 0000000..86191d4
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/cs/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/cs/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Jednotlivé řazení",
+ nestedSort: "Vnořené řazení",
+ ascending: "Vzestupně",
+ descending: "Sestupně",
+ sortingState: "${0} - ${1}",
+ unsorted: "Neřadit tento sloupec",
+ indirectSelectionRadio: "Řádek ${0}, jednotlivý výběr, přepínač",
+ indirectSelectionCheckBox: "Řádek ${0}, vícenásobný výběr, zaškrtávací políčko",
+ selectAll: "Vybrat vše"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/cs/Filter.js b/js/dojo/dojox/grid/enhanced/nls/cs/Filter.js
new file mode 100644
index 0000000..6157fce
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/cs/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/cs/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Vymazat filtr",
+ "filterDefDialogTitle": "Filtr",
+ "ruleTitleTemplate": "Pravidlo ${0}",
+
+ "conditionEqual": "rovná se",
+ "conditionNotEqual": "nerovná se",
+ "conditionLess": "méně než",
+ "conditionLessEqual": "méně nebo rovno",
+ "conditionLarger": "více než",
+ "conditionLargerEqual": "více nebo rovno",
+ "conditionContains": "obsahuje",
+ "conditionIs": "je",
+ "conditionStartsWith": "začíná",
+ "conditionEndWith": "končí",
+ "conditionNotContain": "neobsahuje",
+ "conditionIsNot": "není",
+ "conditionNotStartWith": "nezačíná",
+ "conditionNotEndWith": "nekončí",
+ "conditionBefore": "před",
+ "conditionAfter": "po",
+ "conditionRange": "rozsah",
+ "conditionIsEmpty": "je prázdné",
+
+ "all": "vše",
+ "any": "jakékoli",
+ "relationAll": "všechna pravidla",
+ "waiRelAll": "Porovnat všechna tato pravidla:",
+ "relationAny": "jakákoli pravidla",
+ "waiRelAny": "Porovnat jakákoli z těchto pravidel:",
+ "relationMsgFront": "Shoda",
+ "relationMsgTail": "",
+ "and": "a",
+ "or": "nebo",
+
+ "addRuleButton": "Přidat pravidlo",
+ "waiAddRuleButton": "Přidat nové pravidlo",
+ "removeRuleButton": "Odebrat pravidlo",
+ "waiRemoveRuleButtonTemplate": "Odebrat pravidlo ${0}",
+
+ "cancelButton": "Storno",
+ "waiCancelButton": "Zrušit toto dialogové okno",
+ "clearButton": "Vymazat",
+ "waiClearButton": "Vymazat filtr",
+ "filterButton": "Filtr",
+ "waiFilterButton": "Odeslat filtr",
+
+ "columnSelectLabel": "Sloupec",
+ "waiColumnSelectTemplate": "Sloupec pro pravidlo ${0}",
+ "conditionSelectLabel": "Podmínka",
+ "waiConditionSelectTemplate": "Podmínka pro pravidlo ${0}",
+ "valueBoxLabel": "Hodnota",
+ "waiValueBoxTemplate": "Zadejte hodnotu do filtru pro pravidlo ${0}",
+
+ "rangeTo": "do",
+ "rangeTemplate": "z ${0} do ${1}",
+
+ "statusTipHeaderColumn": "Sloupec",
+ "statusTipHeaderCondition": "Pravidla",
+ "statusTipTitle": "Panel filtrování",
+ "statusTipMsg": "Klepněte zde na panel filtrování, abyste filtrovali hodnoty v ${0}.",
+ "anycolumn": "jakýkoli sloupec",
+ "statusTipTitleNoFilter": "Panel filtrování",
+ "statusTipTitleHasFilter": "Filtr",
+ "statusTipRelAny": "Vyhovovat libovolnému pravidlu",
+ "statusTipRelAll": "Vyhovovat všem pravidlům",
+
+ "defaultItemsName": "položek",
+ "filterBarMsgHasFilterTemplate": "${0} z ${1} ${2} zobrazeno.",
+ "filterBarMsgNoFilterTemplate": "Není použitý žádný filtr",
+
+ "filterBarDefButton": "Definovat filtr",
+ "waiFilterBarDefButton": "Filtrovat tabulku",
+ "a11yFilterBarDefButton": "Filtrovat...",
+ "filterBarClearButton": "Vymazat filtr",
+ "waiFilterBarClearButton": "Vymazat filtr",
+ "closeFilterBarBtn": "Zavřít panel filtrování",
+
+ "clearFilterMsg": "Tímto se odebere filtr a zobrazí všechny dostupné záznamy.",
+ "anyColumnOption": "Jakýkoli sloupec",
+
+ "trueLabel": "Pravda",
+ "falseLabel": "Nepravda"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/cs/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/cs/Pagination.js
new file mode 100644
index 0000000..2f8086d
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/cs/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/cs/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} z ${1} ${0}",
+ "firstTip": "První stránka",
+ "lastTip": "Poslední stránka",
+ "nextTip": "Další stránka",
+ "prevTip": "Předchozí stránka",
+ "itemTitle": "položky",
+ "singularItemTitle": "položka",
+ "pageStepLabelTemplate": "Stránka ${0}",
+ "pageSizeLabelTemplate": "${0} položek na stránku",
+ "allItemsLabelTemplate": "Všechny položky",
+ "gotoButtonTitle": "Přejít na specifickou stránku",
+ "dialogTitle": "Přejít na stránku",
+ "dialogIndication": "Uvést číslo stránky",
+ "pageCountIndication": " (${0} stránky)",
+ "dialogConfirm": "Přejít",
+ "dialogCancel": "Storno",
+ "all": "vše"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/da/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/da/EnhancedGrid.js
new file mode 100644
index 0000000..331ab8f
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/da/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/da/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Enkelt sortering",
+ nestedSort: "Indlejret sortering",
+ ascending: "Stigende",
+ descending: "Faldende",
+ sortingState: "${0} - ${1}",
+ unsorted: "Sortér ikke denne kolonne",
+ indirectSelectionRadio: "Række ${0}, enkelt valg, valgknap",
+ indirectSelectionCheckBox: "Række ${0}, flere valg, afkrydsningsfelt",
+ selectAll: "Markér alle"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/da/Filter.js b/js/dojo/dojox/grid/enhanced/nls/da/Filter.js
new file mode 100644
index 0000000..c382275
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/da/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/da/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Ryd filter",
+ "filterDefDialogTitle": "Filter",
+ "ruleTitleTemplate": "Regel ${0}",
+
+ "conditionEqual": "lig med",
+ "conditionNotEqual": "er forskellig fra",
+ "conditionLess": "er mindre end",
+ "conditionLessEqual": "mindre end eller lig med",
+ "conditionLarger": "er større end",
+ "conditionLargerEqual": "større end eller lig med",
+ "conditionContains": "indeholder",
+ "conditionIs": "er",
+ "conditionStartsWith": "begynder med",
+ "conditionEndWith": "slutter med",
+ "conditionNotContain": "indeholder ikke",
+ "conditionIsNot": "er ikke",
+ "conditionNotStartWith": "begynder ikke med",
+ "conditionNotEndWith": "slutter ikke med",
+ "conditionBefore": "før",
+ "conditionAfter": "efter",
+ "conditionRange": "interval",
+ "conditionIsEmpty": "er tom",
+
+ "all": "alle",
+ "any": "vilkårlig",
+ "relationAll": "alle regler",
+ "waiRelAll": "Matcher alle følgende regler:",
+ "relationAny": "vilkårlige regler",
+ "waiRelAny": "Matcher en eller flere af følgende regler:",
+ "relationMsgFront": "Match",
+ "relationMsgTail": "",
+ "and": "og",
+ "or": "eller",
+
+ "addRuleButton": "Tilføj regel",
+ "waiAddRuleButton": "Tilføj en ny regel",
+ "removeRuleButton": "Fjern regel",
+ "waiRemoveRuleButtonTemplate": "Fjern reglen ${0}",
+
+ "cancelButton": "Annullér",
+ "waiCancelButton": "Annullér denne dialogboks",
+ "clearButton": "Ryd",
+ "waiClearButton": "Ryd filtret",
+ "filterButton": "Filter",
+ "waiFilterButton": "Send filtret",
+
+ "columnSelectLabel": "Kolonne",
+ "waiColumnSelectTemplate": "Kolonne for reglen ${0}",
+ "conditionSelectLabel": "Betingelse",
+ "waiConditionSelectTemplate": "Betingelse for reglen ${0}",
+ "valueBoxLabel": "Værdi",
+ "waiValueBoxTemplate": "Angiv værdi, der skal filtreres efter for reglen ${0}",
+
+ "rangeTo": "til",
+ "rangeTemplate": "fra ${0} til ${1}",
+
+ "statusTipHeaderColumn": "Kolonne",
+ "statusTipHeaderCondition": "Regler",
+ "statusTipTitle": "Filterlinje",
+ "statusTipMsg": "Klik på filterlinjen for at filtrere efter værdier i ${0}.",
+ "anycolumn": "vilkårlig kolonne",
+ "statusTipTitleNoFilter": "Filterlinje",
+ "statusTipTitleHasFilter": "Filter",
+ "statusTipRelAny": "Matcher en hvilken som helst regel.",
+ "statusTipRelAll": "Matcher alle regler.",
+
+ "defaultItemsName": "elementer",
+ "filterBarMsgHasFilterTemplate": "${0} af ${1} ${2} vist.",
+ "filterBarMsgNoFilterTemplate": "Intet filter anvendt",
+
+ "filterBarDefButton": "Definér filter",
+ "waiFilterBarDefButton": "Filtrér tabellen",
+ "a11yFilterBarDefButton": "Filtrér...",
+ "filterBarClearButton": "Ryd filter",
+ "waiFilterBarClearButton": "Ryd filtret",
+ "closeFilterBarBtn": "Luk filterlinje",
+
+ "clearFilterMsg": "Denne funktion fjerner filtret og viser alle tilgængelige records.",
+ "anyColumnOption": "Vilkårlig kolonne",
+
+ "trueLabel": "Sand",
+ "falseLabel": "Falsk"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/da/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/da/Pagination.js
new file mode 100644
index 0000000..0ebcfce
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/da/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/da/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} af ${1} ${0}",
+ "firstTip": "Første side",
+ "lastTip": "Sidste side",
+ "nextTip": "Næste side",
+ "prevTip": "Forrige side",
+ "itemTitle": "elementer",
+ "singularItemTitle": "element",
+ "pageStepLabelTemplate": "Side ${0}",
+ "pageSizeLabelTemplate": "${0} elementer pr. side",
+ "allItemsLabelTemplate": "Alle elementer",
+ "gotoButtonTitle": "Gå til en bestemt side",
+ "dialogTitle": "Gå til side",
+ "dialogIndication": "Angiv sidetallet",
+ "pageCountIndication": " (${0} sider)",
+ "dialogConfirm": "Gå",
+ "dialogCancel": "Annullér",
+ "all": "alle"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/de/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/de/EnhancedGrid.js
new file mode 100644
index 0000000..120b559
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/de/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/de/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Einzelne Sortierung",
+ nestedSort: "Verschachtelte Sortierung",
+ ascending: "Aufsteigend",
+ descending: "Absteigend",
+ sortingState: "${0} - ${1}",
+ unsorted: "Diese Spalte nicht sortieren",
+ indirectSelectionRadio: "Zeile ${0}, einzelne Auswahl, Optionsfeld",
+ indirectSelectionCheckBox: "Zeile ${0}, Mehrfachauswahl, Kontrollkästchen",
+ selectAll: "Alles auswählen"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/de/Filter.js b/js/dojo/dojox/grid/enhanced/nls/de/Filter.js
new file mode 100644
index 0000000..8a1f295
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/de/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/de/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Filter löschen",
+ "filterDefDialogTitle": "Filter",
+ "ruleTitleTemplate": "Regel ${0}",
+
+ "conditionEqual": "gleich",
+ "conditionNotEqual": "ungleich",
+ "conditionLess": "kleiner als",
+ "conditionLessEqual": "kleiner-gleich",
+ "conditionLarger": "größer als",
+ "conditionLargerEqual": "größer-gleich",
+ "conditionContains": "enthält",
+ "conditionIs": "ist",
+ "conditionStartsWith": "beginnt mit",
+ "conditionEndWith": "endet mit",
+ "conditionNotContain": "enthält nicht",
+ "conditionIsNot": "ist nicht",
+ "conditionNotStartWith": "beginnt nicht mit",
+ "conditionNotEndWith": "endet nicht mit",
+ "conditionBefore": "vorher",
+ "conditionAfter": "danach",
+ "conditionRange": "Bereich",
+ "conditionIsEmpty": "ist leer",
+
+ "all": "alle",
+ "any": "beliebige",
+ "relationAll": "alle Regeln",
+ "waiRelAll": "Stimmt mit allen der folgenden Regeln überein:",
+ "relationAny": "beliebige Regeln",
+ "waiRelAny": "Stimmt mit einer beliebigen der folgenden Regeln überein:",
+ "relationMsgFront": "Übereinstimmung",
+ "relationMsgTail": "",
+ "and": "und",
+ "or": "oder",
+
+ "addRuleButton": "Regel hinzufügen",
+ "waiAddRuleButton": "Neue Regel hinzufügen",
+ "removeRuleButton": "Regel entfernen",
+ "waiRemoveRuleButtonTemplate": "Regel ${0} entfernen",
+
+ "cancelButton": "Abbrechen",
+ "waiCancelButton": "Diesen Dialog abbrechen",
+ "clearButton": "Löschen",
+ "waiClearButton": "Den Filter löschen",
+ "filterButton": "Filter",
+ "waiFilterButton": "Den Filter abschicken",
+
+ "columnSelectLabel": "Spalte",
+ "waiColumnSelectTemplate": "Spalte für Regel ${0}",
+ "conditionSelectLabel": "Bedingung",
+ "waiConditionSelectTemplate": "Bedingung für Regel ${0}",
+ "valueBoxLabel": "Wert",
+ "waiValueBoxTemplate": "Wert eingeben, um nach Regel ${0} zu filtern",
+
+ "rangeTo": "bis",
+ "rangeTemplate": "von ${0} bis ${1}",
+
+ "statusTipHeaderColumn": "Spalte",
+ "statusTipHeaderCondition": "Regeln",
+ "statusTipTitle": "Filterleiste",
+ "statusTipMsg": "Klicken Sie auf die Filterleiste hier, um nach Werten in ${0} zu filtern.",
+ "anycolumn": "beliebige Spalte",
+ "statusTipTitleNoFilter": "Filterleiste",
+ "statusTipTitleHasFilter": "Filter",
+ "statusTipRelAny": "Übereinstimmung mit einer oder mehreren beliebigen Regeln.",
+ "statusTipRelAll": "Übereinstimmung mit allen Regeln.",
+
+ "defaultItemsName": "Elemente",
+ "filterBarMsgHasFilterTemplate": "${0} von ${1} ${2} angezeigt.",
+ "filterBarMsgNoFilterTemplate": "Kein Filter angewendet",
+
+ "filterBarDefButton": "Filter definieren",
+ "waiFilterBarDefButton": "Die Tabelle filtern",
+ "a11yFilterBarDefButton": "Filter...",
+ "filterBarClearButton": "Filter löschen",
+ "waiFilterBarClearButton": "Den Filter löschen",
+ "closeFilterBarBtn": "Filterleiste schließen",
+
+ "clearFilterMsg": "Damit wird der Filter gelöscht und es werden alle verfügbaren Sätze angezeigt.",
+ "anyColumnOption": "Beliebige Spalte",
+
+ "trueLabel": "Wahr",
+ "falseLabel": "Falsch"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/de/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/de/Pagination.js
new file mode 100644
index 0000000..67f173e
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/de/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/de/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} von ${1} ${0}",
+ "firstTip": "Erste Seite",
+ "lastTip": "Letzte Seite",
+ "nextTip": "Nächste Seite",
+ "prevTip": "Vorherige Seite",
+ "itemTitle": "Elemente",
+ "singularItemTitle": "Element",
+ "pageStepLabelTemplate": "Seite ${0}",
+ "pageSizeLabelTemplate": "${0} Elemente pro Seite",
+ "allItemsLabelTemplate": "Alle Elemente",
+ "gotoButtonTitle": "Bestimmte Seite aufrufen",
+ "dialogTitle": "Seite aufrufen",
+ "dialogIndication": "Seitenzahl angeben",
+ "pageCountIndication": " (${0} Seiten)",
+ "dialogConfirm": "Start",
+ "dialogCancel": "Abbrechen",
+ "all": "alle"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/el/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/el/EnhancedGrid.js
new file mode 100644
index 0000000..e1179cc
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/el/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/el/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Απλή ταξινόμηση",
+ nestedSort: "Ένθετη ταξινόμηση",
+ ascending: "Αύξουσα",
+ descending: "Φθίνουσα",
+ sortingState: "${0} - ${1}",
+ unsorted: "Χωρίς ταξινόμηση αυτής της στήλης",
+ indirectSelectionRadio: "Γραμμή ${0}, μονή επιλογή, κουμπί επιλογής",
+ indirectSelectionCheckBox: "Γραμμή ${0}, πολλαπλές επιλογές, τετραγωνίδιο επιλογής",
+ selectAll: "Επιλογή όλων"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/el/Filter.js b/js/dojo/dojox/grid/enhanced/nls/el/Filter.js
new file mode 100644
index 0000000..cf1a917
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/el/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/el/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Εκκαθάριση φίλτρου",
+ "filterDefDialogTitle": "Φίλτρο",
+ "ruleTitleTemplate": "Κανόνας ${0}",
+
+ "conditionEqual": "ίσο",
+ "conditionNotEqual": "όχι ίσο",
+ "conditionLess": "είναι μικρότερο από",
+ "conditionLessEqual": "μικρότερο ή ίσο",
+ "conditionLarger": "είναι μεγαλύτερο από",
+ "conditionLargerEqual": "μεγαλύτερο ή ίσο",
+ "conditionContains": "περιέχει",
+ "conditionIs": "είναι",
+ "conditionStartsWith": "αρχίζει από",
+ "conditionEndWith": "τελειώνει σε",
+ "conditionNotContain": "δεν περιέχει",
+ "conditionIsNot": "δεν είναι",
+ "conditionNotStartWith": "δεν αρχίζει από",
+ "conditionNotEndWith": "δεν τελειώνει σε",
+ "conditionBefore": "πριν",
+ "conditionAfter": "μετά",
+ "conditionRange": "εύρος",
+ "conditionIsEmpty": "είναι κενό",
+
+ "all": "όλα",
+ "any": "οποιοδήποτε",
+ "relationAll": "όλοι οι κανόνες",
+ "waiRelAll": "Αντιστοιχία με όλους τους παρακάτω κανόνες:",
+ "relationAny": "οποιοσδήποτε κανόνας",
+ "waiRelAny": "Αντιστοιχία με οποιονδήποτε από τους παρακάτω κανόνες:",
+ "relationMsgFront": "Αντιστοιχία",
+ "relationMsgTail": "",
+ "and": "και",
+ "or": "ή",
+
+ "addRuleButton": "Προσθήκη κανόνα",
+ "waiAddRuleButton": "Προσθήκη νέου κανόνα",
+ "removeRuleButton": "Αφαίρεση κανόνα",
+ "waiRemoveRuleButtonTemplate": "Αφαίρεση κανόνα ${0}",
+
+ "cancelButton": "Ακύρωση",
+ "waiCancelButton": "Ακύρωση αυτού του πλαισίου διαλόγου",
+ "clearButton": "Εκκαθάριση",
+ "waiClearButton": "Εκκαθάριση του φίλτρου",
+ "filterButton": "Φίλτρο",
+ "waiFilterButton": "Υποβολή του φίλτρου",
+
+ "columnSelectLabel": "Στήλη",
+ "waiColumnSelectTemplate": "Στήλη για τον κανόνα ${0}",
+ "conditionSelectLabel": "Συνθήκη",
+ "waiConditionSelectTemplate": "Συνθήκη για τον κανόνα ${0}",
+ "valueBoxLabel": "Τιμή",
+ "waiValueBoxTemplate": "Καταχωρήστε τιμή φίλτρου για τον κανόνα ${0}",
+
+ "rangeTo": "έως",
+ "rangeTemplate": "από ${0} έως ${1}",
+
+ "statusTipHeaderColumn": "Στήλη",
+ "statusTipHeaderCondition": "Κανόνες",
+ "statusTipTitle": "Γραμμή φίλτρου",
+ "statusTipMsg": "Πατήστε στη γραμμή φίλτρου για φιλτράρισμα με βάση τις τιμές στο ${0}.",
+ "anycolumn": "οποιαδήποτε στήλη",
+ "statusTipTitleNoFilter": "Γραμμή φίλτρου",
+ "statusTipTitleHasFilter": "Φίλτρο",
+ "statusTipRelAny": "Αντιστοιχία με οποιουσδήποτε κανόνες.",
+ "statusTipRelAll": "Αντιστοιχία με όλους τους κανόνες.",
+
+ "defaultItemsName": "στοιχεία",
+ "filterBarMsgHasFilterTemplate": "Εμφανίζονται ${0} από ${1} ${2}.",
+ "filterBarMsgNoFilterTemplate": "Δεν έχει εφαρμοστεί φίλτρο",
+
+ "filterBarDefButton": "Ορισμός φίλτρου",
+ "waiFilterBarDefButton": "Φιλτράρισμα του πίνακα",
+ "a11yFilterBarDefButton": "Φιλτράρισμα...",
+ "filterBarClearButton": "Εκκαθάριση φίλτρου",
+ "waiFilterBarClearButton": "Εκκαθάριση του φίλτρου",
+ "closeFilterBarBtn": "Κλείσιμο γραμμής φίλτρου",
+
+ "clearFilterMsg": "Με την επιλογή αυτή θα αφαιρεθεί το φίλτρο και θα εμφανιστούν όλες οι διαθέσιμες εγγραφές.",
+ "anyColumnOption": "Οποιαδήποτε στήλη",
+
+ "trueLabel": "Αληθές",
+ "falseLabel": "Ψευδές"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/el/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/el/Pagination.js
new file mode 100644
index 0000000..b03e995
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/el/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/el/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} από ${1} ${0}",
+ "firstTip": "Πρώτη σελίδα",
+ "lastTip": "Τελευταία σελίδα",
+ "nextTip": "Επόμενη σελίδα",
+ "prevTip": "Προηγούμενη σελίδα",
+ "itemTitle": "στοιχεία",
+ "singularItemTitle": "στοιχείο",
+ "pageStepLabelTemplate": "Σελίδα ${0}",
+ "pageSizeLabelTemplate": "${0} στοιχεία ανά σελίδα",
+ "allItemsLabelTemplate": "Όλα τα στοιχεία",
+ "gotoButtonTitle": "Μετάβαση σε συγκεκριμένη σελίδα",
+ "dialogTitle": "Μετάβαση σε σελίδα",
+ "dialogIndication": "Καθορίστε τον αριθμό της σελίδας",
+ "pageCountIndication": " (${0} σελίδες)",
+ "dialogConfirm": "Μετάβαση",
+ "dialogCancel": "Ακύρωση",
+ "all": "όλα"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/es/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/es/EnhancedGrid.js
new file mode 100644
index 0000000..5886b73
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/es/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/es/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Orden único",
+ nestedSort: "Orden anidado",
+ ascending: "Ascendente",
+ descending: "Descendente",
+ sortingState: "${0} - ${1}",
+ unsorted: "No ordenar esta columna",
+ indirectSelectionRadio: "Fila ${0}, selección única, botón de selección",
+ indirectSelectionCheckBox: "Fila ${0}, selección múltiple, recuadro de selección",
+ selectAll: "Seleccionar todo"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/es/Filter.js b/js/dojo/dojox/grid/enhanced/nls/es/Filter.js
new file mode 100644
index 0000000..8994bb5
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/es/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/es/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Borrar filtro",
+ "filterDefDialogTitle": "Filtro",
+ "ruleTitleTemplate": "Regla ${0}",
+
+ "conditionEqual": "es igual a",
+ "conditionNotEqual": "no es igual a",
+ "conditionLess": "es menor que",
+ "conditionLessEqual": "es menor o igual que",
+ "conditionLarger": "es mayor que",
+ "conditionLargerEqual": "es mayor o igual que",
+ "conditionContains": "contiene",
+ "conditionIs": "es",
+ "conditionStartsWith": "empieza por",
+ "conditionEndWith": "acaba por",
+ "conditionNotContain": "no contiene",
+ "conditionIsNot": "no es",
+ "conditionNotStartWith": "no empieza por",
+ "conditionNotEndWith": "no acaba por",
+ "conditionBefore": "antes",
+ "conditionAfter": "después",
+ "conditionRange": "rango",
+ "conditionIsEmpty": "está vacío",
+
+ "all": "todas",
+ "any": "cualquiera",
+ "relationAll": "todas las reglas",
+ "waiRelAll": "Coincidir con todas las reglas siguientes:",
+ "relationAny": "cualquier regla",
+ "waiRelAny": "Coincidir con cualquiera de las reglas siguientes:",
+ "relationMsgFront": "Coincidir",
+ "relationMsgTail": "",
+ "and": "y",
+ "or": "o",
+
+ "addRuleButton": "Añadir regla",
+ "waiAddRuleButton": "Añadir una regla nueva",
+ "removeRuleButton": "Eliminar regla",
+ "waiRemoveRuleButtonTemplate": "Eliminar la regla ${0}",
+
+ "cancelButton": "Cancelar",
+ "waiCancelButton": "Cancelar este diálogo",
+ "clearButton": "Borrar",
+ "waiClearButton": "Borrar el filtro",
+ "filterButton": "Filtrar",
+ "waiFilterButton": "Enviar el filtro",
+
+ "columnSelectLabel": "Columna",
+ "waiColumnSelectTemplate": "Columna para la regla ${0}",
+ "conditionSelectLabel": "Condición",
+ "waiConditionSelectTemplate": "Condición para la regla ${0}",
+ "valueBoxLabel": "Valor",
+ "waiValueBoxTemplate": "Escriba el valor que se debe filtrar para la regla ${0}",
+
+ "rangeTo": "a",
+ "rangeTemplate": "de ${0} a ${1}",
+
+ "statusTipHeaderColumn": "Columna",
+ "statusTipHeaderCondition": "Reglas",
+ "statusTipTitle": "Barra de filtro",
+ "statusTipMsg": "Pulse aquí en la barra de filtro para filtrar por los valores de ${0}.",
+ "anycolumn": "cualquier columna",
+ "statusTipTitleNoFilter": "Barra de filtro",
+ "statusTipTitleHasFilter": "Filtro",
+ "statusTipRelAny": "Coincidir con cualquier regla.",
+ "statusTipRelAll": "Coincidir con todas las reglas.",
+
+ "defaultItemsName": "elementos",
+ "filterBarMsgHasFilterTemplate": "${0} de ${1} ${2} mostrados.",
+ "filterBarMsgNoFilterTemplate": "Ningún filtro aplicado",
+
+ "filterBarDefButton": "Definir filtro",
+ "waiFilterBarDefButton": "Filtrar la tabla",
+ "a11yFilterBarDefButton": "Filtrar...",
+ "filterBarClearButton": "Borrar filtro",
+ "waiFilterBarClearButton": "Borrar el filtro",
+ "closeFilterBarBtn": "Cerrar barra de filtro",
+
+ "clearFilterMsg": "Esto eliminará el filtro y mostrará todos los registros disponibles.",
+ "anyColumnOption": "Cualquier columna",
+
+ "trueLabel": "Verdadero",
+ "falseLabel": "Falso"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/es/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/es/Pagination.js
new file mode 100644
index 0000000..6bcc4da
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/es/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/es/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} de ${1} ${0}",
+ "firstTip": "Primera página",
+ "lastTip": "Última página",
+ "nextTip": "Página siguiente",
+ "prevTip": "Página anterior",
+ "itemTitle": "elementos",
+ "singularItemTitle": "elemento",
+ "pageStepLabelTemplate": "Página ${0}",
+ "pageSizeLabelTemplate": "${0} elementos por página",
+ "allItemsLabelTemplate": "Todos los elementos",
+ "gotoButtonTitle": "Ir a una página específica",
+ "dialogTitle": "Ir a página",
+ "dialogIndication": "Especifique el número de página",
+ "pageCountIndication": " (${0} páginas)",
+ "dialogConfirm": "Ir",
+ "dialogCancel": "Cancelar",
+ "all": "todas"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/fi/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/fi/EnhancedGrid.js
new file mode 100644
index 0000000..307794a
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/fi/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/fi/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Yksinkertainen lajittelu",
+ nestedSort: "Sisäkkäinen lajittelu",
+ ascending: "Nouseva",
+ descending: "Laskeva",
+ sortingState: "${0} - ${1}",
+ unsorted: "Älä lajittele tätä saraketta",
+ indirectSelectionRadio: "Rivi ${0}, yksittäisvalinta, ruutu",
+ indirectSelectionCheckBox: "Rivi ${0}, monivalinta, valintaruutu",
+ selectAll: "Valitse kaikki"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/fi/Filter.js b/js/dojo/dojox/grid/enhanced/nls/fi/Filter.js
new file mode 100644
index 0000000..e2a5346
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/fi/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/fi/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Tyhjennä suodatin",
+ "filterDefDialogTitle": "Suodatin",
+ "ruleTitleTemplate": "Sääntö ${0}",
+
+ "conditionEqual": "yhtä suuri kuin",
+ "conditionNotEqual": "ei ole yhtä suuri kuin",
+ "conditionLess": "on pienempi kuin",
+ "conditionLessEqual": "pienempi tai yhtä suuri kuin",
+ "conditionLarger": "on suurempi kuin",
+ "conditionLargerEqual": "suurempi tai yhtä suuri kuin",
+ "conditionContains": "sisältää",
+ "conditionIs": "on",
+ "conditionStartsWith": "alussa on",
+ "conditionEndWith": "lopussa on",
+ "conditionNotContain": "ei sisällä",
+ "conditionIsNot": "ei ole",
+ "conditionNotStartWith": "alussa ei ole",
+ "conditionNotEndWith": "lopussa ei ole",
+ "conditionBefore": "ennen",
+ "conditionAfter": "jälkeen",
+ "conditionRange": "vaihtelualue",
+ "conditionIsEmpty": "on tyhjä",
+
+ "all": "kaikki",
+ "any": "mikä tahansa",
+ "relationAll": "kaikki säännöt",
+ "waiRelAll": "Täsmäytä kaikki seuraavat säännöt:",
+ "relationAny": "mitkä tahansa säännöt",
+ "waiRelAny": "Täsmäytä mitkä tahansa seuraavista säännöistä:",
+ "relationMsgFront": "Vastine",
+ "relationMsgTail": "",
+ "and": "ja",
+ "or": "tai",
+
+ "addRuleButton": "Lisää sääntö",
+ "waiAddRuleButton": "Lisää uusi sääntö",
+ "removeRuleButton": "Poista sääntö",
+ "waiRemoveRuleButtonTemplate": "Poista sääntö ${0}",
+
+ "cancelButton": "Peruuta",
+ "waiCancelButton": "Peruuta keskustelu",
+ "clearButton": "Tyhjennä",
+ "waiClearButton": "Tyhjennä suodatin",
+ "filterButton": "Suodata",
+ "waiFilterButton": "Lähetä suodatin",
+
+ "columnSelectLabel": "Sarake",
+ "waiColumnSelectTemplate": "Säännön ${0} sarake",
+ "conditionSelectLabel": "Ehto",
+ "waiConditionSelectTemplate": "Säännön ${0} ehto",
+ "valueBoxLabel": "Arvo",
+ "waiValueBoxTemplate": "Syötä säännön ${0} suodatettava arvo",
+
+ "rangeTo": "kohde",
+ "rangeTemplate": "lähde ${0}, kohde ${1}",
+
+ "statusTipHeaderColumn": "Sarake",
+ "statusTipHeaderCondition": "Säännöt",
+ "statusTipTitle": "Suodatinpalkki",
+ "statusTipMsg": "Napsauta suodatinpalkkia kohteen ${0} arvojen suodattamiseksi.",
+ "anycolumn": "mikä tahansa sarake",
+ "statusTipTitleNoFilter": "Suodatinpalkki",
+ "statusTipTitleHasFilter": "Suodatin",
+ "statusTipRelAny": "Vastaa jotakin sääntöä.",
+ "statusTipRelAll": "Vastaa kaikkia sääntöjä.",
+
+ "defaultItemsName": "nimikkeet",
+ "filterBarMsgHasFilterTemplate": "näkyvissä ${0} / ${1} ${2}.",
+ "filterBarMsgNoFilterTemplate": "Mikään suodatin ei ole käytössä",
+
+ "filterBarDefButton": "Määritä suodatin",
+ "waiFilterBarDefButton": "Suodata taulukko",
+ "a11yFilterBarDefButton": "Suodata...",
+ "filterBarClearButton": "Tyhjennä suodatin",
+ "waiFilterBarClearButton": "Tyhjennä suodatin",
+ "closeFilterBarBtn": "Sulje suodatinpalkki",
+
+ "clearFilterMsg": "Tämä toimenpide poistaa suodattimen ja näyttää kaikki saatavilla olevat tallenteet.",
+ "anyColumnOption": "Mikä tahansa sarake",
+
+ "trueLabel": "Tosi",
+ "falseLabel": "Epätosi"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/fi/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/fi/Pagination.js
new file mode 100644
index 0000000..beae77a
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/fi/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/fi/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} / ${1} ${0}",
+ "firstTip": "Ensimmäinen sivu",
+ "lastTip": "Viimeinen sivu",
+ "nextTip": "Seuraava sivu",
+ "prevTip": "Edellinen sivu",
+ "itemTitle": "nimikkeet",
+ "singularItemTitle": "kohde",
+ "pageStepLabelTemplate": "Sivu ${0}",
+ "pageSizeLabelTemplate": "${0} nimikettä sivua kohti",
+ "allItemsLabelTemplate": "Kaikki nimikkeet",
+ "gotoButtonTitle": "Siirry tietylle sivulle",
+ "dialogTitle": "Siirry sivulle",
+ "dialogIndication": "Kirjoita sivunumero",
+ "pageCountIndication": " (${0} sivua)",
+ "dialogConfirm": "Siirry",
+ "dialogCancel": "Peruuta",
+ "all": "kaikki"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/fr/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/fr/EnhancedGrid.js
new file mode 100644
index 0000000..d1ee539
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/fr/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/fr/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Tri simple",
+ nestedSort: "Tri imbriqué",
+ ascending: "Croissant",
+ descending: "Décroissant",
+ sortingState: "${0} - ${1}",
+ unsorted: "Ne pas trier cette colonne",
+ indirectSelectionRadio: "Ligne ${0}, sélection unique, bouton radio",
+ indirectSelectionCheckBox: "Ligne ${0}, sélection multiple, case à cocher",
+ selectAll: "Tout sélectionner"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/fr/Filter.js b/js/dojo/dojox/grid/enhanced/nls/fr/Filter.js
new file mode 100644
index 0000000..9295240
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/fr/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/fr/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Effacer le filtre",
+ "filterDefDialogTitle": "Filtrer",
+ "ruleTitleTemplate": "Règle ${0}",
+
+ "conditionEqual": "égal",
+ "conditionNotEqual": "est différent de",
+ "conditionLess": "est inférieur à",
+ "conditionLessEqual": "inférieur ou égal",
+ "conditionLarger": "est supérieur à",
+ "conditionLargerEqual": "supérieur ou égal",
+ "conditionContains": "contient",
+ "conditionIs": "est",
+ "conditionStartsWith": "commence par",
+ "conditionEndWith": "se termine par",
+ "conditionNotContain": "ne contient pas",
+ "conditionIsNot": "n'est pas",
+ "conditionNotStartWith": "ne commence pas par",
+ "conditionNotEndWith": "ne se termine pas par",
+ "conditionBefore": "avant",
+ "conditionAfter": "après",
+ "conditionRange": "plage",
+ "conditionIsEmpty": "est vide",
+
+ "all": "tout",
+ "any": "n'importe quelle",
+ "relationAll": "toutes les règles",
+ "waiRelAll": "Satisfaire à toutes les règles suivantes :",
+ "relationAny": "n'importe quelles règles",
+ "waiRelAny": "Satisfaire à une quelconque des règles suivantes :",
+ "relationMsgFront": "Satisfaire",
+ "relationMsgTail": "",
+ "and": "et",
+ "or": "ou",
+
+ "addRuleButton": "Ajouter une règle",
+ "waiAddRuleButton": "Ajouter une nouvelle règle",
+ "removeRuleButton": "Supprimer la règle",
+ "waiRemoveRuleButtonTemplate": "Supprimer la règle ${0}",
+
+ "cancelButton": "Annuler",
+ "waiCancelButton": "Annuler cette boîte de dialogue",
+ "clearButton": "Effacer",
+ "waiClearButton": "Effacer le filtre",
+ "filterButton": "Filtrer",
+ "waiFilterButton": "Soumettre le filtre",
+
+ "columnSelectLabel": "Colonne",
+ "waiColumnSelectTemplate": "Colonne pour la règle ${0}",
+ "conditionSelectLabel": "Condition",
+ "waiConditionSelectTemplate": "Condition pour la règle ${0}",
+ "valueBoxLabel": "Valeur",
+ "waiValueBoxTemplate": "Saisir la valeur à filtrer pour la règle ${0}",
+
+ "rangeTo": "à",
+ "rangeTemplate": "de ${0} à ${1}",
+
+ "statusTipHeaderColumn": "Colonne",
+ "statusTipHeaderCondition": "Règles",
+ "statusTipTitle": "Barre de filtre",
+ "statusTipMsg": "Cliquer sur la barre de filtre ici pour filtrer sur les valeurs de ${0}.",
+ "anycolumn": "n'importe quelle colonne",
+ "statusTipTitleNoFilter": "Barre de filtre",
+ "statusTipTitleHasFilter": "Filtrer",
+ "statusTipRelAny": "Répondre à l'une des règles.",
+ "statusTipRelAll": "Réponde à toutes les régles.",
+
+ "defaultItemsName": "éléments",
+ "filterBarMsgHasFilterTemplate": "${0} sur ${1} ${2} affichés.",
+ "filterBarMsgNoFilterTemplate": "Aucun filtre appliqué",
+
+ "filterBarDefButton": "Définir le filtre",
+ "waiFilterBarDefButton": "Filtrer le tableau",
+ "a11yFilterBarDefButton": "Filtrer...",
+ "filterBarClearButton": "Effacer le filtre",
+ "waiFilterBarClearButton": "Effacer le filtre",
+ "closeFilterBarBtn": "Fermer la barre de filtre",
+
+ "clearFilterMsg": "Cela supprimera le filtre et affichera tous les enregistrements disponibles.",
+ "anyColumnOption": "N'importe quelle colonne",
+
+ "trueLabel": "Vrai",
+ "falseLabel": "Faux"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/fr/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/fr/Pagination.js
new file mode 100644
index 0000000..b9f614d
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/fr/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/fr/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} sur ${1} ${0}",
+ "firstTip": "Première page",
+ "lastTip": "Dernière page",
+ "nextTip": "Page suivante",
+ "prevTip": "Page précédente",
+ "itemTitle": "éléments",
+ "singularItemTitle": "élément",
+ "pageStepLabelTemplate": "Page ${0}",
+ "pageSizeLabelTemplate": "${0} éléments par page",
+ "allItemsLabelTemplate": "Tous les éléments",
+ "gotoButtonTitle": "Accéder à une page spécifique",
+ "dialogTitle": "Accéder à la page",
+ "dialogIndication": "Indiquer le numéro de page",
+ "pageCountIndication": " (${0} pages)",
+ "dialogConfirm": "Accès",
+ "dialogCancel": "Annuler",
+ "all": "tout"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/he/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/he/EnhancedGrid.js
new file mode 100644
index 0000000..b161267
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/he/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/he/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "מיון יחיד",
+ nestedSort: "מיון מקונן",
+ ascending: "עולה",
+ descending: "יורד",
+ sortingState: "${0} - ${1}",
+ unsorted: "אין למיין עמודה זו",
+ indirectSelectionRadio: "שורה ${0}, בחירה יחידה, תיבת בחירה",
+ indirectSelectionCheckBox: "שורה ${0}, בחירה מרובה, תיבת סימון",
+ selectAll: "בחירת הכל"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/he/Filter.js b/js/dojo/dojox/grid/enhanced/nls/he/Filter.js
new file mode 100644
index 0000000..5dd2eaa
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/he/Filter.js
@@ -0,0 +1,90 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/he/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "ניקוי מסנן",
+ "filterDefDialogTitle": "מסנן",
+ "ruleTitleTemplate": "כלל ${0}",
+
+ "conditionEqual": "שווה",
+ "conditionNotEqual": "לא שווה",
+ "conditionLess": "קטן מ",
+ "conditionLessEqual": "קטן או שווה",
+ "conditionLarger": "גדול מ",
+ "conditionLargerEqual": "גדול או שווה",
+ "conditionContains": "מכיל",
+ "conditionIs": "הוא",
+ "conditionStartsWith": "מתחיל ב",
+ "conditionEndWith": "מסתיים ב",
+ "conditionNotContain": "לא מכיל",
+ "conditionIsNot": "אינו",
+ "conditionNotStartWith": "לא מתחיל ב",
+ "conditionNotEndWith": "לא מסתיים ב",
+ "conditionBefore": "לפני",
+ "conditionAfter": "אחרי",
+ "conditionRange": "טווח",
+ "conditionIsEmpty": "ריק",
+
+ "all": "הכל",
+ "any": "כל",
+ "relationAll": "כל הכללים",
+ "waiRelAll": "התאמה לכל הכללים הבאים:",
+ "relationAny": "כל כלל שהוא",
+ "waiRelAny": "התאמה לכל אחד מהכללים הבאים:",
+ "relationMsgFront": "התאמה",
+ "relationMsgTail": "",
+ "and": "ו",
+ "or": "או",
+
+ "addRuleButton": "הוספת כלל",
+ "waiAddRuleButton": "הוספת כלל חדש",
+ "removeRuleButton": "סילוק כלל",
+ "waiRemoveRuleButtonTemplate": "סילוק כלל ${0}",
+
+ "cancelButton": "ביטול",
+ "waiCancelButton": "ביטול תיבת דו-שיח זו",
+ "clearButton": "ניקוי",
+ "waiClearButton": "ניקוי המסנן",
+ "filterButton": "מסנן",
+ "waiFilterButton": "הגשת המסנן",
+
+ "columnSelectLabel": "עמודה",
+ "waiColumnSelectTemplate": "עמודה עבור כלל ${0}",
+ "conditionSelectLabel": "תנאי",
+ "waiConditionSelectTemplate": "תנאי עבור כלל ${0}",
+ "valueBoxLabel": "ערך",
+ "waiValueBoxTemplate": "ציון ערך לסינון עבור כלל ${0}",
+
+ "rangeTo": "עד",
+ "rangeTemplate": "מ-${0} עד ${1}",
+
+ "statusTipHeaderColumn": "עמודה",
+ "statusTipHeaderCondition": "כללים",
+ "statusTipTitle": "סרגל סינון",
+ "statusTipMsg": "לחצו על סרגל הסינון כאן כדי לסנן ערכים ב-${0}.",
+ "anycolumn": "כל עמודה",
+ "statusTipTitleNoFilter": "סרגל סינון",
+ "statusTipTitleHasFilter": "מסנן",
+
+ "defaultItemsName": "פריטים",
+ "filterBarMsgHasFilterTemplate": "מוצג ${0} מתוך ${1} ${2}.",
+ "filterBarMsgNoFilterTemplate": "לא הוחל מסנן",
+
+ "filterBarDefButton": "הגדרת מסנן",
+ "waiFilterBarDefButton": "סינון הטבלה",
+ "a11yFilterBarDefButton": "מסנן...",
+ "filterBarClearButton": "ניקוי מסנן",
+ "waiFilterBarClearButton": "ניקוי המסנן",
+ "closeFilterBarBtn": "סגירת סרגל סינון",
+
+ "clearFilterMsg": "פעולה זו תגרום לסילוק המסנן ולהצגת כל הרשומות הזמינות.",
+ "anyColumnOption": "כל עמודה",
+
+ "trueLabel": "True",
+ "falseLabel": "False"
+})
+//end v1.x content
+);
+
+
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/he/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/he/Pagination.js
new file mode 100644
index 0000000..b343a44
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/he/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/he/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} מתוך ${1} ${0}",
+ "firstTip": "עמוד ראשון",
+ "lastTip": "עמוד אחרון",
+ "nextTip": "העמוד הבא",
+ "prevTip": "העמוד הקודם",
+ "itemTitle": "פריטים",
+ "pageStepLabelTemplate": "עמוד ${0}",
+ "pageSizeLabelTemplate": "${0} פריטים לעמוד",
+ "allItemsLabelTemplate": "כל הפריטים",
+ "gotoButtonTitle": "מעבר לעמוד ספציפי",
+ "dialogTitle": "מעבר לעמוד",
+ "dialogIndication": "ציון מספר העמוד",
+ "pageCountIndication": " (${0} עמודים)",
+ "dialogConfirm": "ביצוע",
+ "dialogCancel": "ביטול",
+ "all": "הכל"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/hr/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/hr/EnhancedGrid.js
new file mode 100644
index 0000000..b97c618
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/hr/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/hr/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Jedan sort",
+ nestedSort: "Ugniježđeni sort",
+ ascending: "Uzlazno",
+ descending: "Silazno",
+ sortingState: "${0} - ${1}",
+ unsorted: "Ne sortiraj ovaj stupac",
+ indirectSelectionRadio: "Red ${0}, jedan izbor, radio kućica",
+ indirectSelectionCheckBox: "Red ${0}, više izbora, kontrolna kućica",
+ selectAll: "Izaberi sve"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/hr/Filter.js b/js/dojo/dojox/grid/enhanced/nls/hr/Filter.js
new file mode 100644
index 0000000..8494a50
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/hr/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/hr/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Brisanje filtera",
+ "filterDefDialogTitle": "Filter",
+ "ruleTitleTemplate": "Pravilo ${0}",
+
+ "conditionEqual": "jednako",
+ "conditionNotEqual": "nije jednako",
+ "conditionLess": "je manje od",
+ "conditionLessEqual": "manje ili jednako",
+ "conditionLarger": "je veće od",
+ "conditionLargerEqual": "veće ili jednako",
+ "conditionContains": "sadrži",
+ "conditionIs": "je",
+ "conditionStartsWith": "počinje sa",
+ "conditionEndWith": "završava sa",
+ "conditionNotContain": "ne sadrži",
+ "conditionIsNot": "nije",
+ "conditionNotStartWith": "ne počinje sa",
+ "conditionNotEndWith": "ne završava sa",
+ "conditionBefore": "prije",
+ "conditionAfter": "poslije",
+ "conditionRange": "raspon",
+ "conditionIsEmpty": "je prazan",
+
+ "all": "svi",
+ "any": "bilo koji",
+ "relationAll": "sva pravila",
+ "waiRelAll": "Usporedi sva sljedeća pravila:",
+ "relationAny": "bilo koja pravila",
+ "waiRelAny": "Usporedi bilo koje od sljedećih pravila:",
+ "relationMsgFront": "Odgovara",
+ "relationMsgTail": "",
+ "and": "i",
+ "or": "ili",
+
+ "addRuleButton": "Bilo koje pravilo",
+ "waiAddRuleButton": "Dodaj novo pravilo",
+ "removeRuleButton": "Ukloni pravilo",
+ "waiRemoveRuleButtonTemplate": "Ukloni pravilo ${0}",
+
+ "cancelButton": "Opoziv",
+ "waiCancelButton": "Opoziv ovog dijaloga",
+ "clearButton": "Obriši",
+ "waiClearButton": "Obriši filter",
+ "filterButton": "Filter",
+ "waiFilterButton": "Predaj filter",
+
+ "columnSelectLabel": "Stupac",
+ "waiColumnSelectTemplate": "Stupac za pravilo ${0}",
+ "conditionSelectLabel": "Uvjet",
+ "waiConditionSelectTemplate": "Uvjet za pravilo ${0}",
+ "valueBoxLabel": "Vrijednost",
+ "waiValueBoxTemplate": "Unesite vrijednost filtera za pravilo ${0}",
+
+ "rangeTo": "do",
+ "rangeTemplate": "od ${0} do ${1}",
+
+ "statusTipHeaderColumn": "Stupac",
+ "statusTipHeaderCondition": "Pravila",
+ "statusTipTitle": "Traka filtera",
+ "statusTipMsg": "Kliknite traku filtera za filtriranje po vrijednostima u ${0}.",
+ "anycolumn": "bilo koji stupac",
+ "statusTipTitleNoFilter": "Traka filtera",
+ "statusTipTitleHasFilter": "Filter",
+ "statusTipRelAny": "Usporedi bilo koja pravila.",
+ "statusTipRelAll": "Usporedi sva pravila.",
+
+ "defaultItemsName": "stavke",
+ "filterBarMsgHasFilterTemplate": "${0} od ${1} ${2} prikazano.",
+ "filterBarMsgNoFilterTemplate": "Filter nije primijenjen",
+
+ "filterBarDefButton": "Definiraj filter",
+ "waiFilterBarDefButton": "Filtriraj tablicu",
+ "a11yFilterBarDefButton": "Filtriraj...",
+ "filterBarClearButton": "Obriši filter",
+ "waiFilterBarClearButton": "Obriši filter",
+ "closeFilterBarBtn": "Zatvori traku filtera",
+
+ "clearFilterMsg": "Ovo uklanja filter i prikazuje sve raspoložive slogove.",
+ "anyColumnOption": "Bilo koji stupac",
+
+ "trueLabel": "True",
+ "falseLabel": "False"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/hr/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/hr/Pagination.js
new file mode 100644
index 0000000..4ddd71b
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/hr/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/hr/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} od ${1} ${0}",
+ "firstTip": "Prva stranica",
+ "lastTip": "Zadnja stranica",
+ "nextTip": "Sljedeća stranica",
+ "prevTip": "Prethodna stranica",
+ "itemTitle": "stavke",
+ "singularItemTitle": "stavka",
+ "pageStepLabelTemplate": "Strana ${0}",
+ "pageSizeLabelTemplate": "${0} stavki po stranici",
+ "allItemsLabelTemplate": "Sve stavke",
+ "gotoButtonTitle": "Idi na određenu stranicu",
+ "dialogTitle": "Idi na stranicu",
+ "dialogIndication": "Navedite broj stranice",
+ "pageCountIndication": " (${0} stranica)",
+ "dialogConfirm": "Idi",
+ "dialogCancel": "Opoziv",
+ "all": "svi"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/hu/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/hu/EnhancedGrid.js
new file mode 100644
index 0000000..d8d4f9a
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/hu/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/hu/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Egyszerű rendezés",
+ nestedSort: "Beágyazott rendezés",
+ ascending: "Növekvő",
+ descending: "Csökkenő",
+ sortingState: "${0} - ${1}",
+ unsorted: "Ne rendezze ezt az oszlopot",
+ indirectSelectionRadio: "${0} sor, egyetlen kijelölés, választógomb",
+ indirectSelectionCheckBox: "${0} sor, több kijelölés, jelölőnégyzet",
+ selectAll: "Összes kijelölése"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/hu/Filter.js b/js/dojo/dojox/grid/enhanced/nls/hu/Filter.js
new file mode 100644
index 0000000..8dd5943
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/hu/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/hu/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Szűrő törlése",
+ "filterDefDialogTitle": "Szűrő",
+ "ruleTitleTemplate": "${0} szabály",
+
+ "conditionEqual": "egyenlő",
+ "conditionNotEqual": "nem egyenlő",
+ "conditionLess": "kisebb mint",
+ "conditionLessEqual": "kisebb vagy egyenlő",
+ "conditionLarger": "nagyobb mint",
+ "conditionLargerEqual": "nagyobb vagy egyenlő",
+ "conditionContains": "tartalmazza",
+ "conditionIs": "pontosan",
+ "conditionStartsWith": "kezdete",
+ "conditionEndWith": "vége",
+ "conditionNotContain": "nem tartalmazza",
+ "conditionIsNot": "nem",
+ "conditionNotStartWith": "nem kezdete",
+ "conditionNotEndWith": "nem vége",
+ "conditionBefore": "előtt",
+ "conditionAfter": "után",
+ "conditionRange": "tartomány",
+ "conditionIsEmpty": "üres",
+
+ "all": "mind",
+ "any": "bármely",
+ "relationAll": "minden szabály",
+ "waiRelAll": "Megfelel a következő összes szabálynak:",
+ "relationAny": "bármely szabály",
+ "waiRelAny": "Megfelel a következő bármely szabálynak:",
+ "relationMsgFront": "Egyezik",
+ "relationMsgTail": "",
+ "and": "és",
+ "or": "vagy",
+
+ "addRuleButton": "Szabály hozzáadása",
+ "waiAddRuleButton": "Új szabály hozzáadása",
+ "removeRuleButton": "Szabály eltávolítása",
+ "waiRemoveRuleButtonTemplate": "${0} szabály eltávolítása",
+
+ "cancelButton": "Mégse",
+ "waiCancelButton": "A párbeszédablak bezárása",
+ "clearButton": "Törlés",
+ "waiClearButton": "A szűrő törlése",
+ "filterButton": "Szűrő",
+ "waiFilterButton": "A szűrő elküldése",
+
+ "columnSelectLabel": "Oszlop",
+ "waiColumnSelectTemplate": "Oszlop a(z) ${0} szabályhoz",
+ "conditionSelectLabel": "Feltétel",
+ "waiConditionSelectTemplate": "Feltétel a(z) ${0} szabályhoz",
+ "valueBoxLabel": "Érték",
+ "waiValueBoxTemplate": "Írja be a szűrni kívánt értéket a(z) ${0} szabályhoz",
+
+ "rangeTo": "-",
+ "rangeTemplate": "${0} - ${1}",
+
+ "statusTipHeaderColumn": "Oszlop",
+ "statusTipHeaderCondition": "Szabályok",
+ "statusTipTitle": "Szűrősáv",
+ "statusTipMsg": "Kattintson a szűrősávra az értékek szűréséhez a következőben: ${0}.",
+ "anycolumn": "bármely oszlop",
+ "statusTipTitleNoFilter": "Szűrősáv",
+ "statusTipTitleHasFilter": "Szűrő",
+ "statusTipRelAny": "Bármely szabálynak megfelel.",
+ "statusTipRelAll": "Minden szabálynak megfelel.",
+
+ "defaultItemsName": "elemek",
+ "filterBarMsgHasFilterTemplate": "${0} / ${1} ${2} megjelenítve.",
+ "filterBarMsgNoFilterTemplate": "Nincs szűrő alkalmazva.",
+
+ "filterBarDefButton": "Szűrő meghatározása",
+ "waiFilterBarDefButton": "Táblázat szűrése",
+ "a11yFilterBarDefButton": "Szűrés...",
+ "filterBarClearButton": "Szűrő törlése",
+ "waiFilterBarClearButton": "A szűrő törlése",
+ "closeFilterBarBtn": "Szűrősáv bezárása",
+
+ "clearFilterMsg": "Eltávolítja a szűrőt és megjeleníti az összes elérhető rekordot.",
+ "anyColumnOption": "Bármely oszlop",
+
+ "trueLabel": "Igaz",
+ "falseLabel": "Hamis"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/hu/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/hu/Pagination.js
new file mode 100644
index 0000000..51ff037
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/hu/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/hu/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} / ${1} ${0}",
+ "firstTip": "Első oldal",
+ "lastTip": "Utolsó oldal",
+ "nextTip": "Következő oldal",
+ "prevTip": "Előző oldal",
+ "itemTitle": "elemek",
+ "singularItemTitle": "elem",
+ "pageStepLabelTemplate": "${0}. oldal",
+ "pageSizeLabelTemplate": "${0} elem oldalanként",
+ "allItemsLabelTemplate": "Összes elem",
+ "gotoButtonTitle": "Ugrás adott oldalra",
+ "dialogTitle": "Ugrás adott oldalra",
+ "dialogIndication": "Adja meg az oldalszámot",
+ "pageCountIndication": " (${0} oldal)",
+ "dialogConfirm": "Mehet",
+ "dialogCancel": "Mégse",
+ "all": "mind"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/it/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/it/EnhancedGrid.js
new file mode 100644
index 0000000..430c858
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/it/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/it/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Ordine singolo",
+ nestedSort: "Ordine nidificato",
+ ascending: "Ascendente",
+ descending: "Decrescente",
+ sortingState: "${0} - ${1}",
+ unsorted: "Non ordinare questa colonna",
+ indirectSelectionRadio: "Riga ${0}, selezione singola, casella di opzione",
+ indirectSelectionCheckBox: "Riga ${0}, selezione multipla, casella di spunta",
+ selectAll: "Seleziona tutto"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/it/Filter.js b/js/dojo/dojox/grid/enhanced/nls/it/Filter.js
new file mode 100644
index 0000000..69d6a6b
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/it/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/it/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Cancella filtro",
+ "filterDefDialogTitle": "Filtro",
+ "ruleTitleTemplate": "Regola ${0}",
+
+ "conditionEqual": "uguale a",
+ "conditionNotEqual": "non uguale a",
+ "conditionLess": "minore di",
+ "conditionLessEqual": "minore di o uguale a",
+ "conditionLarger": "maggiore di",
+ "conditionLargerEqual": "maggiore di o uguale a",
+ "conditionContains": "contiene",
+ "conditionIs": "è",
+ "conditionStartsWith": "inizia con",
+ "conditionEndWith": "finisce con",
+ "conditionNotContain": "non contiene",
+ "conditionIsNot": "non è",
+ "conditionNotStartWith": "non inizia con",
+ "conditionNotEndWith": "non finisce con",
+ "conditionBefore": "prima",
+ "conditionAfter": "dopo",
+ "conditionRange": "intervallo",
+ "conditionIsEmpty": "è vuoto",
+
+ "all": "tutte",
+ "any": "qualsiasi",
+ "relationAll": "tutte le regole",
+ "waiRelAll": "Confronta con tutte le seguenti regole:",
+ "relationAny": "qualsiasi regola",
+ "waiRelAny": "Confronta con qualsiasi delle seguenti regole:",
+ "relationMsgFront": "Confronta",
+ "relationMsgTail": "",
+ "and": "e",
+ "or": "o",
+
+ "addRuleButton": "Aggiungi regola",
+ "waiAddRuleButton": "Aggiungi una nuova regola",
+ "removeRuleButton": "Rimuovi regola",
+ "waiRemoveRuleButtonTemplate": "Rimuovi regola ${0}",
+
+ "cancelButton": "Annulla",
+ "waiCancelButton": "Annulla questa finestra di dialogo",
+ "clearButton": "Cancella",
+ "waiClearButton": "Cancella il filtro",
+ "filterButton": "Filtro",
+ "waiFilterButton": "Inoltra il filtro",
+
+ "columnSelectLabel": "Colonna",
+ "waiColumnSelectTemplate": "Colonna per la regola ${0}",
+ "conditionSelectLabel": "Condizione",
+ "waiConditionSelectTemplate": "Condizione per la regola ${0}",
+ "valueBoxLabel": "Valore",
+ "waiValueBoxTemplate": "Immettere il valore da filtrare per la regola ${0}",
+
+ "rangeTo": "a",
+ "rangeTemplate": "da ${0} a ${1}",
+
+ "statusTipHeaderColumn": "Colonna",
+ "statusTipHeaderCondition": "Regole",
+ "statusTipTitle": "Barra di filtro",
+ "statusTipMsg": "Fare clic sulla barra di filtro qui per filtrare sui valori in ${0}.",
+ "anycolumn": "qualsiasi colonna",
+ "statusTipTitleNoFilter": "Barra di filtro",
+ "statusTipTitleHasFilter": "Filtro",
+ "statusTipRelAny": "Corrispondenza con qualsiasi regola.",
+ "statusTipRelAll": "Corrispondenza con tutte le regole.",
+
+ "defaultItemsName": "elementi",
+ "filterBarMsgHasFilterTemplate": "${0} di ${1} ${2} visualizzati.",
+ "filterBarMsgNoFilterTemplate": "Nessun filtro applicato",
+
+ "filterBarDefButton": "Definisci filtro",
+ "waiFilterBarDefButton": "Filtra la tabella",
+ "a11yFilterBarDefButton": "Filtro...",
+ "filterBarClearButton": "Cancella filtro",
+ "waiFilterBarClearButton": "Cancella il filtro",
+ "closeFilterBarBtn": "Chiudi barra di filtro",
+
+ "clearFilterMsg": "Questo rimuoverà il filtro e visualizzerà tutti i record disponibili.",
+ "anyColumnOption": "Qualsiasi colonna",
+
+ "trueLabel": "Vero",
+ "falseLabel": "Falso"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/it/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/it/Pagination.js
new file mode 100644
index 0000000..96d042c
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/it/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/it/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} di ${1} ${0}",
+ "firstTip": "Prima pagina",
+ "lastTip": "Ultima pagina",
+ "nextTip": "Pagina successiva ",
+ "prevTip": "Pagina precedente ",
+ "itemTitle": "elementi ",
+ "singularItemTitle": "elemento",
+ "pageStepLabelTemplate": "Pagina ${0}",
+ "pageSizeLabelTemplate": "${0} elementi per pagina ",
+ "allItemsLabelTemplate": "Tutti gli elementi",
+ "gotoButtonTitle": "Vai a una pagina specifica ",
+ "dialogTitle": "Vai a pagina ",
+ "dialogIndication": "Specificare il numero di pagina",
+ "pageCountIndication": " (${0} pagine)",
+ "dialogConfirm": "Vai",
+ "dialogCancel": "Annulla",
+ "all": "tutte"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/ja/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/ja/EnhancedGrid.js
new file mode 100644
index 0000000..851e550
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ja/EnhancedGrid.js
@@ -0,0 +1,16 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ja/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "単一ソート",
+ nestedSort: "ネスト・ソート",
+ ascending: "昇順",
+ descending: "降順",
+ sortingState: "${0} - ${1}",
+ unsorted: "この列をソートしない",
+ indirectSelectionRadio: "行 ${0}、単一選択、ラジオ・ボックス",
+ indirectSelectionCheckBox: "行 ${0}、複数選択、チェック・ボックス",
+ selectAll: "すべてを選択"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/ja/Filter.js b/js/dojo/dojox/grid/enhanced/nls/ja/Filter.js
new file mode 100644
index 0000000..0366bfc
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ja/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ja/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "フィルターのクリア",
+ "filterDefDialogTitle": "フィルター",
+ "ruleTitleTemplate": "ルール ${0}",
+
+ "conditionEqual": "等しい",
+ "conditionNotEqual": "等しくない",
+ "conditionLess": "より小",
+ "conditionLessEqual": "より小または等しい",
+ "conditionLarger": "より大",
+ "conditionLargerEqual": "より大または等しい",
+ "conditionContains": "含む",
+ "conditionIs": "該当する",
+ "conditionStartsWith": "先頭",
+ "conditionEndWith": "末尾",
+ "conditionNotContain": "含まない",
+ "conditionIsNot": "該当しない",
+ "conditionNotStartWith": "先頭が異なる",
+ "conditionNotEndWith": "末尾が異なる",
+ "conditionBefore": "より前",
+ "conditionAfter": "より後",
+ "conditionRange": "範囲",
+ "conditionIsEmpty": "空である",
+
+ "all": "すべて",
+ "any": "いずれか",
+ "relationAll": "すべてのルール",
+ "waiRelAll": "次のルールのすべてに一致:",
+ "relationAny": "いずれかのルール",
+ "waiRelAny": "次のルールのいずれかに一致:",
+ "relationMsgFront": "一致",
+ "relationMsgTail": "",
+ "and": "かつ",
+ "or": "または",
+
+ "addRuleButton": "ルールの追加",
+ "waiAddRuleButton": "新規ルールの追加",
+ "removeRuleButton": "ルールの削除",
+ "waiRemoveRuleButtonTemplate": "ルール ${0} の削除",
+
+ "cancelButton": "キャンセル",
+ "waiCancelButton": "このダイアログをキャンセル",
+ "clearButton": "クリア",
+ "waiClearButton": "フィルターのクリア",
+ "filterButton": "フィルター",
+ "waiFilterButton": "フィルターの実行依頼",
+
+ "columnSelectLabel": "列",
+ "waiColumnSelectTemplate": "ルール ${0} の列",
+ "conditionSelectLabel": "条件",
+ "waiConditionSelectTemplate": "ルール ${0} の条件",
+ "valueBoxLabel": "値",
+ "waiValueBoxTemplate": "ルール ${0} を検出するフィルター操作のための値を入力",
+
+ "rangeTo": "範囲",
+ "rangeTemplate": "${0} から ${1} まで",
+
+ "statusTipHeaderColumn": "列",
+ "statusTipHeaderCondition": "ルール",
+ "statusTipTitle": "フィルター・バー",
+ "statusTipMsg": "このフィルター・バーをクリックして、${0} の値にフィルターを適用します。",
+ "anycolumn": "いずれかの列",
+ "statusTipTitleNoFilter": "フィルター・バー",
+ "statusTipTitleHasFilter": "フィルター",
+ "statusTipRelAny": "いずれかのルールに一致。",
+ "statusTipRelAll": "すべてのルールに一致。",
+
+ "defaultItemsName": "項目",
+ "filterBarMsgHasFilterTemplate": "${0}/${1} ${2} が表示されました。",
+ "filterBarMsgNoFilterTemplate": "フィルターが適用されていません",
+
+ "filterBarDefButton": "フィルターの定義",
+ "waiFilterBarDefButton": "表のフィルタリング",
+ "a11yFilterBarDefButton": "フィルター...",
+ "filterBarClearButton": "フィルターのクリア",
+ "waiFilterBarClearButton": "フィルターのクリア",
+ "closeFilterBarBtn": "フィルター・バーを閉じる",
+
+ "clearFilterMsg": "これによりフィルターが解除され、使用可能なレコードがすべて表示されます。",
+ "anyColumnOption": "いずれかの列",
+
+ "trueLabel": "True",
+ "falseLabel": "False"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/ja/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/ja/Pagination.js
new file mode 100644
index 0000000..90cd698
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ja/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ja/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3}/${1} ${0}",
+ "firstTip": "最初のページ",
+ "lastTip": "最後のページ",
+ "nextTip": "次のページ",
+ "prevTip": "前のページ",
+ "itemTitle": "項目",
+ "singularItemTitle": "項目",
+ "pageStepLabelTemplate": "ページ ${0}",
+ "pageSizeLabelTemplate": "ページ当たり ${0} 項目",
+ "allItemsLabelTemplate": "すべての項目",
+ "gotoButtonTitle": "特定のページに移動",
+ "dialogTitle": "ページの移動",
+ "dialogIndication": "ページ番号を指定してください",
+ "pageCountIndication": " (${0} ページ)",
+ "dialogConfirm": "実行",
+ "dialogCancel": "キャンセル",
+ "all": "すべて"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/kk/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/kk/EnhancedGrid.js
new file mode 100644
index 0000000..d1aeac2
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/kk/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/kk/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Бір рет сұрыптау",
+ nestedSort: "Кірістірілген сұрыптау",
+ ascending: "Артуы бойынша",
+ descending: "Кемуі бойынша",
+ sortingState: "${0} - ${1}",
+ unsorted: "Бұл бағанды сұрыптамау",
+ indirectSelectionRadio: "${0}-жол, жалғыз элементті таңдау, бір түймешікті таңдау тақтасы",
+ indirectSelectionCheckBox: "${0}-жол, бірнеше элементті таңдау, құсбелгі",
+ selectAll: "Барлығын таңдау"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/kk/Filter.js b/js/dojo/dojox/grid/enhanced/nls/kk/Filter.js
new file mode 100644
index 0000000..fbe4cd2
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/kk/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/kk/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Сүзгіні тазалау",
+ "filterDefDialogTitle": "Сүзгі",
+ "ruleTitleTemplate": "${0} ережесі",
+
+ "conditionEqual": "тең",
+ "conditionNotEqual": "тең емес",
+ "conditionLess": "аздау",
+ "conditionLessEqual": "аздау немесе тең",
+ "conditionLarger": "үлкендеу",
+ "conditionLargerEqual": "үлкендеу немесе тең",
+ "conditionContains": "құрамында бар",
+ "conditionIs": "–",
+ "conditionStartsWith": "басталады",
+ "conditionEndWith": "аяқталады",
+ "conditionNotContain": "құрамында жоқ",
+ "conditionIsNot": "емес",
+ "conditionNotStartWith": "басталмайды",
+ "conditionNotEndWith": "аяқталмайды",
+ "conditionBefore": "алдында",
+ "conditionAfter": "артында",
+ "conditionRange": "ауқым",
+ "conditionIsEmpty": "– бос",
+
+ "all": "барлығы",
+ "any": "кез келген",
+ "relationAll": "барлық ережелер",
+ "waiRelAll": "Барлық мына ережелерге сәйкес:",
+ "relationAny": "кез келген ереже",
+ "waiRelAny": "Мына ережелерге сәйкес:",
+ "relationMsgFront": "Сәйкес келу",
+ "relationMsgTail": "",
+ "and": "және",
+ "or": "немесе",
+
+ "addRuleButton": "Ереже қосу",
+ "waiAddRuleButton": "Жаңа ереже қосу",
+ "removeRuleButton": "Ережені алып тастау",
+ "waiRemoveRuleButtonTemplate": "${0} ережесін алып тастау",
+
+ "cancelButton": "Болдырмау",
+ "waiCancelButton": "Осы тілқатысу терезесін болдырмау",
+ "clearButton": "Тазалау ",
+ "waiClearButton": "Сүзгіні тазалау",
+ "filterButton": "Сүзгі",
+ "waiFilterButton": "Сүзгіні жіберу",
+
+ "columnSelectLabel": "Баған",
+ "waiColumnSelectTemplate": "${0} ережесінің бағаны",
+ "conditionSelectLabel": "Шарт",
+ "waiConditionSelectTemplate": "${0} ережесінің шарты",
+ "valueBoxLabel": "Мән",
+ "waiValueBoxTemplate": "${0} ережесін сүзу үшін мәнді енгізу",
+
+ "rangeTo": "неге",
+ "rangeTemplate": "${0} мәнінен ${1} мәніне",
+
+ "statusTipHeaderColumn": "Баған",
+ "statusTipHeaderCondition": "Ережелер",
+ "statusTipTitle": "Сүзгі тақтасы",
+ "statusTipMsg": "${0} ішіндегі мәндер бойынша сүзу үшін сүзгі тақтасын нұқыңыз.",
+ "anycolumn": "кез келген баған",
+ "statusTipTitleNoFilter": "Сүзгі тақтасы",
+ "statusTipTitleHasFilter": "Сүзгі",
+ "statusTipRelAny": "Кез келген ережелерді сәйкестендіріңіз.",
+ "statusTipRelAll": "Барлық ережелерді сәйкестендіріңіз.",
+
+ "defaultItemsName": "элементтер",
+ "filterBarMsgHasFilterTemplate": "${1} ${2} ішінен ${0} көрсетілді.",
+ "filterBarMsgNoFilterTemplate": "Сүзгі қолданылмады",
+
+ "filterBarDefButton": "Сүзгіні анықтау",
+ "waiFilterBarDefButton": "Кестені сүзу",
+ "a11yFilterBarDefButton": "Сүзгі...",
+ "filterBarClearButton": "Сүзгіні тазалау",
+ "waiFilterBarClearButton": "Сүзгіні тазалау",
+ "closeFilterBarBtn": "Сүзгі тақтасын жабу",
+
+ "clearFilterMsg": "Бұл сүзгіні жояды және барлық қол жетімді жазбаларды көрсетеді.",
+ "anyColumnOption": "Кез келген баған",
+
+ "trueLabel": "Шын",
+ "falseLabel": "Жалған"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/kk/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/kk/Pagination.js
new file mode 100644
index 0000000..baa56fe
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/kk/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/kk/Pagination", //begin v1.x content
+({
+ "descTemplate": "${1} ${0} элементтің ${2} - ${3} элементі",
+ "firstTip": "Бірінші бет",
+ "lastTip": "Соңғы бет",
+ "nextTip": "Келесі бет",
+ "prevTip": "Алдыңғы бет",
+ "itemTitle": "элементтер",
+ "singularItemTitle": "элемент",
+ "pageStepLabelTemplate": "Бет ${0}",
+ "pageSizeLabelTemplate": "Бетіне ${0} элемент",
+ "allItemsLabelTemplate": "Барлық элементтер",
+ "gotoButtonTitle": "Белгілі бір бетке өту",
+ "dialogTitle": "Бетке өту",
+ "dialogIndication": "Бет нөмірін көрсету",
+ "pageCountIndication": " (${0} бет)",
+ "dialogConfirm": "Өту",
+ "dialogCancel": "Болдырмау",
+ "all": "барлығы"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/ko/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/ko/EnhancedGrid.js
new file mode 100644
index 0000000..9e0d07b
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ko/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ko/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "단일 정렬",
+ nestedSort: "중첩된 정렬",
+ ascending: "오름차순",
+ descending: "내림차순",
+ sortingState: "${0} - ${1}",
+ unsorted: "이 컬럼은 정렬하지 마십시오",
+ indirectSelectionRadio: "행 ${0}, 단일 선택, 라디오 상자",
+ indirectSelectionCheckBox: "행 ${0}, 다중 선택, 선택란",
+ selectAll: "모두 선택"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/ko/Filter.js b/js/dojo/dojox/grid/enhanced/nls/ko/Filter.js
new file mode 100644
index 0000000..0b909b2
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ko/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ko/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "필터 지우기",
+ "filterDefDialogTitle": "필터",
+ "ruleTitleTemplate": "규칙 ${0}",
+
+ "conditionEqual": "같음",
+ "conditionNotEqual": "같지 않음",
+ "conditionLess": "미만",
+ "conditionLessEqual": "이하",
+ "conditionLarger": "초과",
+ "conditionLargerEqual": "이상",
+ "conditionContains": "포함",
+ "conditionIs": "다음과 같음",
+ "conditionStartsWith": "다음으로 시작",
+ "conditionEndWith": "다음으로 종료",
+ "conditionNotContain": "포함하지 않음",
+ "conditionIsNot": "다음이 아님",
+ "conditionNotStartWith": "다음으로 시작하지 않음",
+ "conditionNotEndWith": "다음으로 종료하지 않음",
+ "conditionBefore": "이전",
+ "conditionAfter": "이후",
+ "conditionRange": "범위",
+ "conditionIsEmpty": "다음이 비어있음",
+
+ "all": "모두",
+ "any": "임의",
+ "relationAll": "모든 규칙",
+ "waiRelAll": "다음 규칙에 모두 일치:",
+ "relationAny": "임의 규칙",
+ "waiRelAny": "다음 규칙 중에 일치:",
+ "relationMsgFront": "일치",
+ "relationMsgTail": "",
+ "and": "및",
+ "or": "또는",
+
+ "addRuleButton": "규칙 추가",
+ "waiAddRuleButton": "새 규칙 추가",
+ "removeRuleButton": "규칙 제거",
+ "waiRemoveRuleButtonTemplate": "${0} 규칙 제거",
+
+ "cancelButton": "취소",
+ "waiCancelButton": "이 대화 상자 취소",
+ "clearButton": "지우기",
+ "waiClearButton": "해당 필터 지우기",
+ "filterButton": "필터",
+ "waiFilterButton": "필터 제출",
+
+ "columnSelectLabel": "컬럼",
+ "waiColumnSelectTemplate": "${0} 규칙에 대한 컬럼",
+ "conditionSelectLabel": "조건",
+ "waiConditionSelectTemplate": "${0} 규칙에 대한 조건",
+ "valueBoxLabel": "값",
+ "waiValueBoxTemplate": "${0} 규칙에 대해 필터링할 값 입력",
+
+ "rangeTo": "다음에서 종료",
+ "rangeTemplate": "${0}에서 ${1}까지",
+
+ "statusTipHeaderColumn": "컬럼",
+ "statusTipHeaderCondition": "규칙",
+ "statusTipTitle": "필터 표시줄",
+ "statusTipMsg": "${0}의 값을 필터링하려면 이 필터 표시줄을 클릭하십시오.",
+ "anycolumn": "임의의 컬럼",
+ "statusTipTitleNoFilter": "필터 표시줄",
+ "statusTipTitleHasFilter": "필터",
+ "statusTipRelAny": "임의 규칙과 일치.",
+ "statusTipRelAll": "모든 규칙과 일치.",
+
+ "defaultItemsName": "항목",
+ "filterBarMsgHasFilterTemplate": "${0}/${1} ${2} 표시됨",
+ "filterBarMsgNoFilterTemplate": "적용된 필터 없음",
+
+ "filterBarDefButton": "필터 정의",
+ "waiFilterBarDefButton": "표 필터링",
+ "a11yFilterBarDefButton": "필터...",
+ "filterBarClearButton": "필터 지우기",
+ "waiFilterBarClearButton": "해당 필터 지우기",
+ "closeFilterBarBtn": "필터 표시줄 닫기",
+
+ "clearFilterMsg": "이로 인해 해당 필터가 제거되며 사용 가능한 모든 레코드가 표시됩니다.",
+ "anyColumnOption": "임의의 컬럼",
+
+ "trueLabel": "True",
+ "falseLabel": "False"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/ko/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/ko/Pagination.js
new file mode 100644
index 0000000..39c88b1
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ko/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ko/Pagination", //begin v1.x content
+({
+ "descTemplate": "${1} ${0} 중 ${2} - ${3}",
+ "firstTip": "첫 번째 페이지",
+ "lastTip": "마지막 페이지",
+ "nextTip": "다음 페이지",
+ "prevTip": "이전 페이지",
+ "itemTitle": "항목",
+ "singularItemTitle": "항목",
+ "pageStepLabelTemplate": "페이지 ${0}",
+ "pageSizeLabelTemplate": "페이지 당 ${0} 항목",
+ "allItemsLabelTemplate": "모든 항목",
+ "gotoButtonTitle": "특정 페이지로 이동",
+ "dialogTitle": "페이지로 이동",
+ "dialogIndication": "페이지 번호 지정",
+ "pageCountIndication": " (${0} 페이지)",
+ "dialogConfirm": "이동",
+ "dialogCancel": "취소",
+ "all": "모두"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/nb/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/nb/EnhancedGrid.js
new file mode 100644
index 0000000..660d223
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/nb/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/nb/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Enkeltsortering",
+ nestedSort: "Nestet sortering",
+ ascending: "Stigende",
+ descending: "Synkende",
+ sortingState: "${0} - ${1}",
+ unsorted: "Ikke sorter denne kolonnen",
+ indirectSelectionRadio: "Rad ${0}, enkeltvalg, valgknapp",
+ indirectSelectionCheckBox: "Rad ${0}, flervalg, avmerkingsboks",
+ selectAll: "Velg alle"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/nb/Filter.js b/js/dojo/dojox/grid/enhanced/nls/nb/Filter.js
new file mode 100644
index 0000000..5a58363
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/nb/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/nb/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Tøm filter",
+ "filterDefDialogTitle": "Filter",
+ "ruleTitleTemplate": "Regel ${0}",
+
+ "conditionEqual": "er lik",
+ "conditionNotEqual": "er ikke lik",
+ "conditionLess": "er mindre enn",
+ "conditionLessEqual": "mindre enn eller lik",
+ "conditionLarger": "er større enn",
+ "conditionLargerEqual": "større enn eller lik",
+ "conditionContains": "inneholder",
+ "conditionIs": "er",
+ "conditionStartsWith": "starter med",
+ "conditionEndWith": "slutter med",
+ "conditionNotContain": "inneholder ikke",
+ "conditionIsNot": "er ikke",
+ "conditionNotStartWith": "starter ikke med",
+ "conditionNotEndWith": "slutter ikke med",
+ "conditionBefore": "før",
+ "conditionAfter": "etter",
+ "conditionRange": "område",
+ "conditionIsEmpty": "er tom",
+
+ "all": "alle",
+ "any": "minst en",
+ "relationAll": "alle regler",
+ "waiRelAll": "Samsvar med alle disse reglene:",
+ "relationAny": "minst en regel",
+ "waiRelAny": "Samsvar med minst en av disse reglene:",
+ "relationMsgFront": "Samsvar med",
+ "relationMsgTail": "",
+ "and": "og",
+ "or": "eller",
+
+ "addRuleButton": "Legg til regel",
+ "waiAddRuleButton": "Legg til en ny regel",
+ "removeRuleButton": "Fjern regel",
+ "waiRemoveRuleButtonTemplate": "Fjern regel ${0}",
+
+ "cancelButton": "Avbryt",
+ "waiCancelButton": "Avbryt denne dialogboksen",
+ "clearButton": "Tøm",
+ "waiClearButton": "Tøm filteret",
+ "filterButton": "Filtrer",
+ "waiFilterButton": "Send filteret",
+
+ "columnSelectLabel": "Kolonne",
+ "waiColumnSelectTemplate": "Kolonne for regel ${0}",
+ "conditionSelectLabel": "Betingelse",
+ "waiConditionSelectTemplate": "Betingelse for regel ${0}",
+ "valueBoxLabel": "Verdi",
+ "waiValueBoxTemplate": "Oppgi verdi som skal filtreres for regel ${0}",
+
+ "rangeTo": "til",
+ "rangeTemplate": "fra ${0} til ${1}",
+
+ "statusTipHeaderColumn": "Kolonne",
+ "statusTipHeaderCondition": "Regler",
+ "statusTipTitle": "Filterlinje",
+ "statusTipMsg": "Klikk på filterlinjen her for å filtrere på verdiene i ${0}.",
+ "anycolumn": "enhver kolonne",
+ "statusTipTitleNoFilter": "Filterlinje",
+ "statusTipTitleHasFilter": "Filter",
+ "statusTipRelAny": "Samsvar med minst en regel.",
+ "statusTipRelAll": "Samsvar med alle regler.",
+
+ "defaultItemsName": "elementer",
+ "filterBarMsgHasFilterTemplate": "${0} av ${1} ${2} vist.",
+ "filterBarMsgNoFilterTemplate": "Ikke brukt filter",
+
+ "filterBarDefButton": "Definer filter",
+ "waiFilterBarDefButton": "Filtrer tabellen",
+ "a11yFilterBarDefButton": "Filtrer...",
+ "filterBarClearButton": "Tøm filter",
+ "waiFilterBarClearButton": "Tøm filteret",
+ "closeFilterBarBtn": "Lukk filterlinjen",
+
+ "clearFilterMsg": "Dette fjerner filteret og viser alle tilgjengelige poster.",
+ "anyColumnOption": "Minst en kolonne",
+
+ "trueLabel": "Sann",
+ "falseLabel": "Usann"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/nb/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/nb/Pagination.js
new file mode 100644
index 0000000..ae43787
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/nb/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/nb/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} av ${1} ${0}",
+ "firstTip": "Første side",
+ "lastTip": "Siste side",
+ "nextTip": "Neste side",
+ "prevTip": "Forrige side",
+ "itemTitle": "elementer",
+ "singularItemTitle": "element",
+ "pageStepLabelTemplate": "Side ${0}",
+ "pageSizeLabelTemplate": "${0} elementer per side",
+ "allItemsLabelTemplate": "Alle elementer",
+ "gotoButtonTitle": "Gå til en bestemt side",
+ "dialogTitle": "Gå til side",
+ "dialogIndication": "Oppgi sidetallet",
+ "pageCountIndication": " (${0} sider)",
+ "dialogConfirm": "Utfør",
+ "dialogCancel": "Avbryt",
+ "all": "alle"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/nl/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/nl/EnhancedGrid.js
new file mode 100644
index 0000000..d74e154
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/nl/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/nl/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Enkelvoudig sorteren",
+ nestedSort: "Genest sorteren",
+ ascending: "Oplopend",
+ descending: "Aflopend",
+ sortingState: "${0} - ${1}",
+ unsorted: "Deze kolom niet sorteren",
+ indirectSelectionRadio: "Rij ${0}, enkele selectie, keuzerondje",
+ indirectSelectionCheckBox: "Rij ${0}, meerdere selecties, selectievakje",
+ selectAll: "Alles selecteren"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/nl/Filter.js b/js/dojo/dojox/grid/enhanced/nls/nl/Filter.js
new file mode 100644
index 0000000..4456d4b
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/nl/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/nl/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Filter wissen",
+ "filterDefDialogTitle": "Filteren",
+ "ruleTitleTemplate": "Regel ${0}",
+
+ "conditionEqual": "gelijk aan",
+ "conditionNotEqual": "niet gelijk aan",
+ "conditionLess": "is kleiner dan",
+ "conditionLessEqual": "kleiner dan of gelijk aan",
+ "conditionLarger": "is groter dan",
+ "conditionLargerEqual": "groter dan of gelijk aan",
+ "conditionContains": "bevat",
+ "conditionIs": "is",
+ "conditionStartsWith": "begint met",
+ "conditionEndWith": "eindigt op",
+ "conditionNotContain": "bevat niet",
+ "conditionIsNot": "is niet",
+ "conditionNotStartWith": "begint niet met",
+ "conditionNotEndWith": "eindigt niet op",
+ "conditionBefore": "voor",
+ "conditionAfter": "na",
+ "conditionRange": "bereik",
+ "conditionIsEmpty": "is leeg",
+
+ "all": "alle",
+ "any": "een of meer",
+ "relationAll": "alle regels",
+ "waiRelAll": "Voldoen aan al deze regels:",
+ "relationAny": "een of meer regels",
+ "waiRelAny": "Voldoen aan een van deze regels:",
+ "relationMsgFront": "Voldoen aan",
+ "relationMsgTail": "",
+ "and": "en",
+ "or": "of",
+
+ "addRuleButton": "Regel toevoegen",
+ "waiAddRuleButton": "Een nieuwe regel toevoegen",
+ "removeRuleButton": "Regel verwijderen",
+ "waiRemoveRuleButtonTemplate": "Regel ${0} verwijderen",
+
+ "cancelButton": "Annuleren",
+ "waiCancelButton": "Dit dialoogvenster annuleren",
+ "clearButton": "Leegmaken",
+ "waiClearButton": "Het filter wissen",
+ "filterButton": "Filteren",
+ "waiFilterButton": "Het filter verzenden",
+
+ "columnSelectLabel": "Kolom",
+ "waiColumnSelectTemplate": "Kolom voor regel ${0}",
+ "conditionSelectLabel": "Voorwaarde",
+ "waiConditionSelectTemplate": "Voorwaarde voor regel ${0}",
+ "valueBoxLabel": "Waarde",
+ "waiValueBoxTemplate": "Geef een filterwaarde op voor regel ${0}",
+
+ "rangeTo": "tot",
+ "rangeTemplate": "van ${0} tot ${1}",
+
+ "statusTipHeaderColumn": "Kolom",
+ "statusTipHeaderCondition": "Regels",
+ "statusTipTitle": "Filterbalk",
+ "statusTipMsg": "Klik hier op de filterbalk om te filteren op waarden in ${0}.",
+ "anycolumn": "een kolom",
+ "statusTipTitleNoFilter": "Filterbalk",
+ "statusTipTitleHasFilter": "Filter",
+ "statusTipRelAny": "Voldoen aan een van de regels.",
+ "statusTipRelAll": "Voldoen aan alle regels.",
+
+ "defaultItemsName": "items",
+ "filterBarMsgHasFilterTemplate": "${0} van ${1} ${2} afgebeeld.",
+ "filterBarMsgNoFilterTemplate": "Geen filter toegepast",
+
+ "filterBarDefButton": "Filter definiëren",
+ "waiFilterBarDefButton": "De tabel filteren",
+ "a11yFilterBarDefButton": "Filteren...",
+ "filterBarClearButton": "Filter wissen",
+ "waiFilterBarClearButton": "Het filter wissen",
+ "closeFilterBarBtn": "Filterbalk sluiten",
+
+ "clearFilterMsg": "Hiermee verwijdert u het filter en worden alle beschikbare records afgebeeld.",
+ "anyColumnOption": "Een kolom",
+
+ "trueLabel": "Waar",
+ "falseLabel": "Onwaar"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/nl/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/nl/Pagination.js
new file mode 100644
index 0000000..c18a2ea
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/nl/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/nl/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} van ${1} ${0}",
+ "firstTip": "Eerste pagina",
+ "lastTip": "Laatste pagina",
+ "nextTip": "Volgende pagina",
+ "prevTip": "Vorige pagina",
+ "itemTitle": "items",
+ "singularItemTitle": "item",
+ "pageStepLabelTemplate": "Pagina ${0}",
+ "pageSizeLabelTemplate": "${0} items per pagina",
+ "allItemsLabelTemplate": "Alle items",
+ "gotoButtonTitle": "Ga naar bepaalde pagina",
+ "dialogTitle": "Ga naar pagina",
+ "dialogIndication": "Geef het paginanummer op",
+ "pageCountIndication": " (${0} pagina's)",
+ "dialogConfirm": "Go",
+ "dialogCancel": "Annuleren",
+ "all": "alle"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/pl/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/pl/EnhancedGrid.js
new file mode 100644
index 0000000..0fe4701
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/pl/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/pl/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Pojedyncze sortowanie",
+ nestedSort: "Zagnieżdżone sortowanie",
+ ascending: "Rosnąco",
+ descending: "Malejąco",
+ sortingState: "${0} - ${1}",
+ unsorted: "Nie sortuj tej kolumny",
+ indirectSelectionRadio: "Wiersz ${0}, pojedynczy wybór, zestaw przełączników",
+ indirectSelectionCheckBox: "Wiersz ${0}, wybór wielokrotny, pole wyboru",
+ selectAll: "Wybierz wszystko"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/pl/Filter.js b/js/dojo/dojox/grid/enhanced/nls/pl/Filter.js
new file mode 100644
index 0000000..16737ae
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/pl/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/pl/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Wyczyść filtr",
+ "filterDefDialogTitle": "Filtr",
+ "ruleTitleTemplate": "Reguła ${0}",
+
+ "conditionEqual": "równe",
+ "conditionNotEqual": "różne od",
+ "conditionLess": "mniejsze od",
+ "conditionLessEqual": "mniejsze lub równe",
+ "conditionLarger": "większe od",
+ "conditionLargerEqual": "większe lub równe",
+ "conditionContains": "zawiera",
+ "conditionIs": "jest",
+ "conditionStartsWith": "zaczyna się od",
+ "conditionEndWith": "kończy się na",
+ "conditionNotContain": "nie zawiera",
+ "conditionIsNot": "nie jest",
+ "conditionNotStartWith": "nie zaczyna się od",
+ "conditionNotEndWith": "nie kończy się na",
+ "conditionBefore": "przed",
+ "conditionAfter": "po",
+ "conditionRange": "zakres",
+ "conditionIsEmpty": "jest pusty",
+
+ "all": "wszystkie",
+ "any": "dowolne",
+ "relationAll": "wszystkie reguły",
+ "waiRelAll": "Dopasuj wszystkie poniższe reguły:",
+ "relationAny": "dowolna reguła",
+ "waiRelAny": "Dopasuj dowolną z poniższych reguł:",
+ "relationMsgFront": "Dopasuj",
+ "relationMsgTail": "",
+ "and": "i",
+ "or": "lub",
+
+ "addRuleButton": "Dodaj regułę",
+ "waiAddRuleButton": "Dodaj nową regułę",
+ "removeRuleButton": "Usuń regułę",
+ "waiRemoveRuleButtonTemplate": "Usuń regułę ${0}",
+
+ "cancelButton": "Anuluj",
+ "waiCancelButton": "Anuluj to okno dialogowe",
+ "clearButton": "Wyczyść",
+ "waiClearButton": "Wyczyść filtr",
+ "filterButton": "Filtruj",
+ "waiFilterButton": "Wprowadź ten filtr",
+
+ "columnSelectLabel": "Kolumna",
+ "waiColumnSelectTemplate": "Kolumna dla reguły ${0}",
+ "conditionSelectLabel": "Warunek",
+ "waiConditionSelectTemplate": "Warunek dla reguły ${0}",
+ "valueBoxLabel": "Wartość",
+ "waiValueBoxTemplate": "Wprowadź wartość, aby filtrować dla reguły ${0}",
+
+ "rangeTo": "do",
+ "rangeTemplate": "od ${0} do ${1}",
+
+ "statusTipHeaderColumn": "Kolumna",
+ "statusTipHeaderCondition": "Reguły",
+ "statusTipTitle": "Pasek filtru",
+ "statusTipMsg": "Kliknij pasek filtru tutaj, aby filtrować według wartości w ${0}.",
+ "anycolumn": "dowolna kolumna",
+ "statusTipTitleNoFilter": "Pasek filtru",
+ "statusTipTitleHasFilter": "Filtr",
+ "statusTipRelAny": "Dopasuj do dowolnej z reguł.",
+ "statusTipRelAll": "Dopasuj do wszystkich reguł.",
+
+ "defaultItemsName": "elementy",
+ "filterBarMsgHasFilterTemplate": "Wyświetlane ${0} z ${1} ${2}.",
+ "filterBarMsgNoFilterTemplate": "Filtr wyłączony",
+
+ "filterBarDefButton": "Zdefiniuj filtr",
+ "waiFilterBarDefButton": "Filtruj tabelę",
+ "a11yFilterBarDefButton": "Filtruj...",
+ "filterBarClearButton": "Wyczyść filtr",
+ "waiFilterBarClearButton": "Wyczyść filtr",
+ "closeFilterBarBtn": "Zamknij pasek filtru",
+
+ "clearFilterMsg": "Filtr zostanie usunięty i wyświetlone będą wszystkie dostępne rekordy.",
+ "anyColumnOption": "Dowolna kolumna",
+
+ "trueLabel": "Prawda",
+ "falseLabel": "Fałsz"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/pl/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/pl/Pagination.js
new file mode 100644
index 0000000..c8db8df
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/pl/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/pl/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} z ${1} ${0}",
+ "firstTip": "Pierwsza strona",
+ "lastTip": "Ostatnia strona",
+ "nextTip": "Następna strona",
+ "prevTip": "Poprzednia strona",
+ "itemTitle": "poz.",
+ "singularItemTitle": "pozycja",
+ "pageStepLabelTemplate": "Strona ${0}",
+ "pageSizeLabelTemplate": "${0} poz. na stronę",
+ "allItemsLabelTemplate": "Wszystkie pozycje",
+ "gotoButtonTitle": "Idź do konkretnej strony",
+ "dialogTitle": "Idź do strony",
+ "dialogIndication": "Podaj numer strony",
+ "pageCountIndication": " (${0} str.)",
+ "dialogConfirm": "Wykonaj",
+ "dialogCancel": "Anuluj",
+ "all": "wszystkie"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/pt-br/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/pt-br/EnhancedGrid.js
new file mode 100644
index 0000000..093461c
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/pt-br/EnhancedGrid.js
@@ -0,0 +1,16 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/pt-br/EnhancedGrid", ({
+ singleSort: "Classificação Única",
+ nestedSort: "Classificação Aninhada",
+ ascending: "Crescente",
+ descending: "Decrescente",
+ sortingState: "${0} - ${1}",
+ unsorted: "Não classificar esta coluna",
+ indirectSelectionRadio: "Linha ${0}, seleção única, caixa de opção",
+ indirectSelectionCheckBox: "Linha ${0}, seleção múltipla, caixa de seleção",
+ selectAll: "Selecionar todos"
+})
+
+
+); \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/nls/pt-br/Filter.js b/js/dojo/dojox/grid/enhanced/nls/pt-br/Filter.js
new file mode 100644
index 0000000..dcc9553
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/pt-br/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/pt-br/Filter", ({
+ "clearFilterDialogTitle": "Limpar Filtro",
+ "filterDefDialogTitle": "Filtrar",
+ "ruleTitleTemplate": "Regra ${0}",
+
+ "conditionEqual": "igual",
+ "conditionNotEqual": "não é igual",
+ "conditionLess": "é menor que",
+ "conditionLessEqual": "menor que ou igual",
+ "conditionLarger": "é maior que",
+ "conditionLargerEqual": "maior que ou igual",
+ "conditionContains": "contém",
+ "conditionIs": "é",
+ "conditionStartsWith": "começa com",
+ "conditionEndWith": "termina com",
+ "conditionNotContain": "não contém",
+ "conditionIsNot": "não é",
+ "conditionNotStartWith": "não começa com",
+ "conditionNotEndWith": "não termina com",
+ "conditionBefore": "antes",
+ "conditionAfter": "após",
+ "conditionRange": "intervalo",
+ "conditionIsEmpty": "está vazio",
+
+ "all": "todos",
+ "any": "qualquer",
+ "relationAll": "todas as regras",
+ "waiRelAll": "Corresponder todas as regras a seguir:",
+ "relationAny": "quaisquer regras",
+ "waiRelAny": "Corresponder qualquer uma das regras a seguir:",
+ "relationMsgFront": "Corresponder",
+ "relationMsgTail": "",
+ "and": "e",
+ "or": "ou",
+
+ "addRuleButton": "Incluir Regra",
+ "waiAddRuleButton": "Incluir uma nova regra",
+ "removeRuleButton": "Remover Regra",
+ "waiRemoveRuleButtonTemplate": "Remover regra ${0}",
+
+ "cancelButton": "Cancelar",
+ "waiCancelButton": "cancelar este diálogo",
+ "clearButton": "Limpar",
+ "waiClearButton": "Limpar o filtro",
+ "filterButton": "Filtrar",
+ "waiFilterButton": "Submeter o filtro",
+
+ "columnSelectLabel": "Coluna",
+ "waiColumnSelectTemplate": "Coluna para a regra ${0}",
+ "conditionSelectLabel": "Condição",
+ "waiConditionSelectTemplate": "Condição para a regra ${0}",
+ "valueBoxLabel": "Valor",
+ "waiValueBoxTemplate": "Inserir o valor para filtro para a regra ${0}",
+
+ "rangeTo": "para",
+ "rangeTemplate": "de ${0} para ${1}",
+
+ "statusTipHeaderColumn": "Coluna",
+ "statusTipHeaderCondition": "Regras",
+ "statusTipTitle": "Barra de Filtro",
+ "statusTipMsg": "Clique aqui na barra de filtro para filtrar os valores em ${0}.",
+ "anycolumn": "qualquer coluna",
+ "statusTipTitleNoFilter": "Barra de Filtro",
+ "statusTipTitleHasFilter": "Filtrar",
+
+ "defaultItemsName": "itens",
+ "filterBarMsgHasFilterTemplate": "${0} de ${1} ${2} mostrado.",
+ "filterBarMsgNoFilterTemplate": "Nenhum filtro aplicado",
+
+ "filterBarDefButton": "Definir filtro",
+ "waiFilterBarDefButton": "Filtrar a tabela",
+ "a11yFilterBarDefButton": "Filtrar...",
+ "filterBarClearButton": "Limpar Filtro",
+ "waiFilterBarClearButton": "Limpar o filtro",
+ "closeFilterBarBtn": "Fechar a barra de filtro",
+
+ "clearFilterMsg": "Isso removerá o filtro e mostrará todos os registros disponíveis.",
+ "anyColumnOption": "Qualquer Coluna",
+
+ "trueLabel": "Verdadeiro",
+ "falseLabel": "Falso"
+})
+
+
+
+
+); \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/nls/pt-br/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/pt-br/Pagination.js
new file mode 100644
index 0000000..25bf82b
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/pt-br/Pagination.js
@@ -0,0 +1,36 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/pt-br/Pagination", ({
+ // ${0}: string
+ // unit of item, identified by "itemTitle"
+ // ${2}: number
+ // start item index of current page
+ // ${3}: number
+ // end item index of current page
+ // ${1}: number
+ // total number of all items
+ // example:
+ // the total number is 200, the unit of item is "items"
+ // rows per page is 20, current page is 1, then the description
+ // would be looked as below:
+ // | 1 - 20 of 200 items
+ "descTemplate": "${2} - ${3} de ${1} ${0}",
+ "firstTip": "Primeira Página",
+ "lastTip": "Última Página",
+ "nextTip": "Próxima Página",
+ "prevTip": "Página Anterior",
+ "itemTitle": "itens",
+ "singularItemTitle": "item",
+ "pageStepLabelTemplate": "Página ${0}",
+ "pageSizeLabelTemplate": "${0} itens por página",
+ "allItemsLabelTemplate": "Todos os itens",
+ "gotoButtonTitle": "Ir para uma página específica",
+ "dialogTitle": "Ir para a página",
+ "dialogIndication": "Especificar o número da página",
+ "pageCountIndication": " (${0} páginas)",
+ "dialogConfirm": "Ir",
+ "dialogCancel": "Cancelar",
+ "all": "todos"
+})
+
+); \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/nls/pt-pt/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/pt-pt/EnhancedGrid.js
new file mode 100644
index 0000000..f5c5340
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/pt-pt/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/pt-pt/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Ordenação única",
+ nestedSort: "Ordenação imbricada",
+ ascending: "Ascendente",
+ descending: "Descendente",
+ sortingState: "${0} - ${1}",
+ unsorted: "Não ordenar esta coluna",
+ indirectSelectionRadio: "Fila ${0}, selecção única, caixa de opção",
+ indirectSelectionCheckBox: "Fila ${0}, selecção múltipla, quadrado de confirmação",
+ selectAll: "Seleccionar tudo"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/pt-pt/Filter.js b/js/dojo/dojox/grid/enhanced/nls/pt-pt/Filter.js
new file mode 100644
index 0000000..beb4937
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/pt-pt/Filter.js
@@ -0,0 +1,90 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/pt-pt/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Limpar filtro",
+ "filterDefDialogTitle": "Filtro",
+ "ruleTitleTemplate": "Regra ${0}",
+
+ "conditionEqual": "igual",
+ "conditionNotEqual": "não é igual",
+ "conditionLess": "é menor do que",
+ "conditionLessEqual": "menor ou igual",
+ "conditionLarger": "é maior do que",
+ "conditionLargerEqual": "maior ou igual",
+ "conditionContains": "contém",
+ "conditionIs": "é",
+ "conditionStartsWith": "começa com",
+ "conditionEndWith": "termina com",
+ "conditionNotContain": "não contém",
+ "conditionIsNot": "não é",
+ "conditionNotStartWith": "não começa com",
+ "conditionNotEndWith": "não termina com",
+ "conditionBefore": "antes",
+ "conditionAfter": "após",
+ "conditionRange": "intervalo",
+ "conditionIsEmpty": "está vazio",
+
+ "all": "tudo",
+ "any": "qualquer",
+ "relationAll": "todas as regras",
+ "waiRelAll": "Corresponder a todas as seguintes regras:",
+ "relationAny": "quaisquer regras",
+ "waiRelAny": "Corresponder a qualquer uma das seguintes regras:",
+ "relationMsgFront": "Corresponder",
+ "relationMsgTail": "",
+ "and": "and",
+ "or": "or",
+
+ "addRuleButton": "Adicionar regra",
+ "waiAddRuleButton": "Adicionar uma nova regra",
+ "removeRuleButton": "Remover regra",
+ "waiRemoveRuleButtonTemplate": "Remover regra ${0}",
+
+ "cancelButton": "Cancelar",
+ "waiCancelButton": "Cancelar esta caixa de diálogo",
+ "clearButton": "Limpar",
+ "waiClearButton": "Limpar o filtro",
+ "filterButton": "Filtro",
+ "waiFilterButton": "Submeter o filtro",
+
+ "columnSelectLabel": "Coluna",
+ "waiColumnSelectTemplate": "Coluna para a regra ${0}",
+ "conditionSelectLabel": "Condição",
+ "waiConditionSelectTemplate": "Condição para a regra ${0}",
+ "valueBoxLabel": "Valor",
+ "waiValueBoxTemplate": "Introduzir valor para filtrar para a regra ${0}",
+
+ "rangeTo": "a",
+ "rangeTemplate": "de ${0} a ${1}",
+
+ "statusTipHeaderColumn": "Coluna",
+ "statusTipHeaderCondition": "Regras",
+ "statusTipTitle": "Barra do filtro",
+ "statusTipMsg": "Faça clique na barra de filtro para filtrar os valores em ${0}.",
+ "anycolumn": "qualquer coluna",
+ "statusTipTitleNoFilter": "Barra do filtro",
+ "statusTipTitleHasFilter": "Filtro",
+
+ "defaultItemsName": "itens",
+ "filterBarMsgHasFilterTemplate": "${0} de ${1} ${2} apresentado(s).",
+ "filterBarMsgNoFilterTemplate": "Nenhum filtro aplicado",
+
+ "filterBarDefButton": "Definir filtro",
+ "waiFilterBarDefButton": "Filtrar a tabela",
+ "a11yFilterBarDefButton": "Filtrar...",
+ "filterBarClearButton": "Limpar filtro",
+ "waiFilterBarClearButton": "Limpar o filtro",
+ "closeFilterBarBtn": "Fechar barra de filtro",
+
+ "clearFilterMsg": "Este procedimento irá remover o filtro e apresentar todos os registos disponíveis.",
+ "anyColumnOption": "Qualquer coluna",
+
+ "trueLabel": "True",
+ "falseLabel": "False"
+})
+//end v1.x content
+);
+
+
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/pt-pt/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/pt-pt/Pagination.js
new file mode 100644
index 0000000..ac54ab0
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/pt-pt/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/pt-pt/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} de ${1} ${0}",
+ "firstTip": "Primeira página",
+ "lastTip": "Última página",
+ "nextTip": "Página seguinte",
+ "prevTip": "Página anterior",
+ "itemTitle": "itens",
+ "pageStepLabelTemplate": "Página ${0}",
+ "pageSizeLabelTemplate": "${0} itens por página",
+ "allItemsLabelTemplate": "Todos os itens",
+ "gotoButtonTitle": "Avançar para uma página específica",
+ "dialogTitle": "Avançar para a página",
+ "dialogIndication": "Especificar o número de página",
+ "pageCountIndication": " (${0} páginas)",
+ "dialogConfirm": "Ir",
+ "dialogCancel": "Cancelar",
+ "all": "tudo"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/pt/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/pt/EnhancedGrid.js
new file mode 100644
index 0000000..b09ab48
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/pt/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/pt/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Classificação Única",
+ nestedSort: "Classificação Aninhada",
+ ascending: "Ascendente",
+ descending: "Descendente",
+ sortingState: "${0} - ${1}",
+ unsorted: "Não classificar esta coluna",
+ indirectSelectionRadio: "Linha ${0}, seleção única, botão de seleção",
+ indirectSelectionCheckBox: "Linha ${0}, seleção múltipla, caixa de seleção",
+ selectAll: "Selecionar todos"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/pt/Filter.js b/js/dojo/dojox/grid/enhanced/nls/pt/Filter.js
new file mode 100644
index 0000000..7974304
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/pt/Filter.js
@@ -0,0 +1,92 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/pt/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Limpar Filtro",
+ "filterDefDialogTitle": "Filtrar",
+ "ruleTitleTemplate": "Regra ${0}",
+
+ "conditionEqual": "igual",
+ "conditionNotEqual": "não é igual",
+ "conditionLess": "é menor que",
+ "conditionLessEqual": "menor ou igual a",
+ "conditionLarger": "é maior que",
+ "conditionLargerEqual": "maior ou igual a",
+ "conditionContains": "contém",
+ "conditionIs": "é",
+ "conditionStartsWith": "inicia com",
+ "conditionEndWith": "termina com",
+ "conditionNotContain": "não contém",
+ "conditionIsNot": "não é",
+ "conditionNotStartWith": "não inicia com",
+ "conditionNotEndWith": "não termina com",
+ "conditionBefore": "antes",
+ "conditionAfter": "depois",
+ "conditionRange": "intervalo",
+ "conditionIsEmpty": "está vazio",
+
+ "all": "todos",
+ "any": "qualquer um",
+ "relationAll": "todas as regras",
+ "waiRelAll": "Corresponder a todas as seguintes regras:",
+ "relationAny": "qualquer regra",
+ "waiRelAny": "Corresponder a qualquer uma das seguintes regras:",
+ "relationMsgFront": "Corresponder",
+ "relationMsgTail": "",
+ "and": "e",
+ "or": "ou",
+
+ "addRuleButton": "Incluir Regra",
+ "waiAddRuleButton": "Incluir uma nova regra",
+ "removeRuleButton": "Remover Regra",
+ "waiRemoveRuleButtonTemplate": "Remover regra ${0}",
+
+ "cancelButton": "Cancelar",
+ "waiCancelButton": "Cancelar este diálogo",
+ "clearButton": "Limpar",
+ "waiClearButton": "Limpar o filtro",
+ "filterButton": "Filtrar",
+ "waiFilterButton": "Enviar o filtro",
+
+ "columnSelectLabel": "Coluna",
+ "waiColumnSelectTemplate": "Coluna para a regra ${0}",
+ "conditionSelectLabel": "Condição",
+ "waiConditionSelectTemplate": "Condição para a regra ${0}",
+ "valueBoxLabel": "Valor",
+ "waiValueBoxTemplate": "Insira o valor para filtragem da regra ${0}",
+
+ "rangeTo": "a",
+ "rangeTemplate": "de ${0} a ${1}",
+
+ "statusTipHeaderColumn": "Coluna",
+ "statusTipHeaderCondition": "Regras",
+ "statusTipTitle": "Barra de Filtragem",
+ "statusTipMsg": "Clique na barra de filtragem aqui para filtrar os valores de ${0}.",
+ "anycolumn": "qualquer coluna",
+ "statusTipTitleNoFilter": "Barra de Filtragem",
+ "statusTipTitleHasFilter": "Filtrar",
+ "statusTipRelAny": "Quaisquer Regras.",
+ "statusTipRelAll": "Todas as Regras.",
+
+ "defaultItemsName": "itens",
+ "filterBarMsgHasFilterTemplate": "${0} de ${1} ${2} mostrados.",
+ "filterBarMsgNoFilterTemplate": "Nenhum filtro aplicado",
+
+ "filterBarDefButton": "Definir filtro",
+ "waiFilterBarDefButton": "Filtrar a tabela",
+ "a11yFilterBarDefButton": "Filtrar...",
+ "filterBarClearButton": "Limpar filtro",
+ "waiFilterBarClearButton": "Limpar o filtro",
+ "closeFilterBarBtn": "Fechar a barra de filtragem",
+
+ "clearFilterMsg": "Isso removerá o filtro e mostrará todos os registros disponíveis.",
+ "anyColumnOption": "Qualquer Coluna",
+
+ "trueLabel": "Verdadeiro",
+ "falseLabel": "Falso"
+})
+//end v1.x content
+);
+
+
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/pt/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/pt/Pagination.js
new file mode 100644
index 0000000..5a1320d
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/pt/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/pt/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} de ${1} ${0}",
+ "firstTip": "Primeira Página",
+ "lastTip": "Última Página",
+ "nextTip": "Próxima página",
+ "prevTip": "Página anterior",
+ "itemTitle": "itens",
+ "singularItemTitle": "item",
+ "pageStepLabelTemplate": "Página ${0}",
+ "pageSizeLabelTemplate": "${0} itens por página",
+ "allItemsLabelTemplate": "Todos os itens",
+ "gotoButtonTitle": "Acesse uma página específica",
+ "dialogTitle": "Acesse a Página",
+ "dialogIndication": "Especifique o número da página",
+ "pageCountIndication": " (${0} páginas)",
+ "dialogConfirm": "Ir",
+ "dialogCancel": "Cancelar",
+ "all": "todos"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/ro/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/ro/EnhancedGrid.js
new file mode 100644
index 0000000..0415b11
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ro/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ro/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Sortare singulară",
+ nestedSort: "Sortare imbricată",
+ ascending: "Crescător",
+ descending: "Descrescător",
+ sortingState: "${0} - ${1}",
+ unsorted: "Nu se sortează această coloană",
+ indirectSelectionRadio: "Rândul ${0}, selecţie singulară, casetă radio",
+ indirectSelectionCheckBox: "Rândul ${0}, selecţie multiplă, casetă de bifare",
+ selectAll: "Selectare tot"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/ro/Filter.js b/js/dojo/dojox/grid/enhanced/nls/ro/Filter.js
new file mode 100644
index 0000000..ba2879c
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ro/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ro/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Ştergere filtru",
+ "filterDefDialogTitle": "Filtru",
+ "ruleTitleTemplate": "Regulă ${0}",
+
+ "conditionEqual": "egal",
+ "conditionNotEqual": "nu este egal",
+ "conditionLess": "este mai mic decât",
+ "conditionLessEqual": "mai mic sau egal",
+ "conditionLarger": "este mai mare decât",
+ "conditionLargerEqual": "mai mare sau egal",
+ "conditionContains": "conţine",
+ "conditionIs": "este",
+ "conditionStartsWith": "începe cu",
+ "conditionEndWith": "se termină cu",
+ "conditionNotContain": "nu conţine",
+ "conditionIsNot": "nu este",
+ "conditionNotStartWith": "nu începe cu",
+ "conditionNotEndWith": "nu se termină cu",
+ "conditionBefore": "înaintea",
+ "conditionAfter": "după",
+ "conditionRange": "interval",
+ "conditionIsEmpty": "este gol",
+
+ "all": "toate",
+ "any": "oricare",
+ "relationAll": "toate regulile",
+ "waiRelAll": "Răspundeţi tuturor regulilor următoare:",
+ "relationAny": "oricare reguli",
+ "waiRelAny": "Răspundeţi oricărei dintre regulile următoare:",
+ "relationMsgFront": "Răspuns",
+ "relationMsgTail": "",
+ "and": "şi",
+ "or": "sau",
+
+ "addRuleButton": "Adăugare regulă",
+ "waiAddRuleButton": "Adăugare regulă nouă",
+ "removeRuleButton": "Înlăturare regulă",
+ "waiRemoveRuleButtonTemplate": "Înlăturare regulă ${0}",
+
+ "cancelButton": "Anulare",
+ "waiCancelButton": "Anulaţi acest dialog",
+ "clearButton": "Ştergere",
+ "waiClearButton": "Ştergeţi filtrul",
+ "filterButton": "Filtru",
+ "waiFilterButton": "Lansaţi în execuţie filtrul",
+
+ "columnSelectLabel": "Coloană",
+ "waiColumnSelectTemplate": "Coloană pentru regulă ${0}",
+ "conditionSelectLabel": "Condiţie",
+ "waiConditionSelectTemplate": "Condiţie pentru regula ${0}",
+ "valueBoxLabel": "Valoare",
+ "waiValueBoxTemplate": "Introduceţi valoarea pentru filtrarea pentru regulă ${0}",
+
+ "rangeTo": "la",
+ "rangeTemplate": "din ${0} la ${1}",
+
+ "statusTipHeaderColumn": "Coloană",
+ "statusTipHeaderCondition": "Reguli",
+ "statusTipTitle": "Bară de filtru",
+ "statusTipMsg": "Faceţi clic pe bara de filtru aici pentru a filtra valorile în ${0}.",
+ "anycolumn": "orice coloană",
+ "statusTipTitleNoFilter": "Bară de filtru",
+ "statusTipTitleHasFilter": "Filtru",
+ "statusTipRelAny": "Potrivire orice regulă.",
+ "statusTipRelAll": "Potrivire toate regulile.",
+
+ "defaultItemsName": "articole",
+ "filterBarMsgHasFilterTemplate": "${0} din ${1} ${2} afişate.",
+ "filterBarMsgNoFilterTemplate": "Niciun filtru nu este aplicat",
+
+ "filterBarDefButton": "Definire filtru",
+ "waiFilterBarDefButton": "Filtrare tabelă",
+ "a11yFilterBarDefButton": "Filtru...",
+ "filterBarClearButton": "Ştergere filtru",
+ "waiFilterBarClearButton": "Ştergeţi filtrul",
+ "closeFilterBarBtn": "Închidere bară de filtru",
+
+ "clearFilterMsg": "Aceasta va înlătura filtrul şi va afişa toate înregistrările disponibile.",
+ "anyColumnOption": "Orice coloană",
+
+ "trueLabel": "Adevărat",
+ "falseLabel": "Fals"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/ro/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/ro/Pagination.js
new file mode 100644
index 0000000..633a192
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ro/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ro/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} din ${1} ${0}",
+ "firstTip": "Prima pagină",
+ "lastTip": "Ultima pagină",
+ "nextTip": "Următoarea pagină",
+ "prevTip": "Pagina anterioarp",
+ "itemTitle": "articole",
+ "singularItemTitle": "articol",
+ "pageStepLabelTemplate": "Pagina ${0}",
+ "pageSizeLabelTemplate": "${0} articole pe pagină",
+ "allItemsLabelTemplate": "Toate articolele",
+ "gotoButtonTitle": "Deplasare la o pagină anumită",
+ "dialogTitle": "Deplasare la pagină",
+ "dialogIndication": "Specificaţi numărul de pagină",
+ "pageCountIndication": " (${0} pagini)",
+ "dialogConfirm": "Deplasare",
+ "dialogCancel": "Anulare",
+ "all": "toate"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/ru/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/ru/EnhancedGrid.js
new file mode 100644
index 0000000..cdb44ac
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ru/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ru/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Простая сортировка",
+ nestedSort: "Вложенная сортировка",
+ ascending: "По возрастанию",
+ descending: "По убыванию",
+ sortingState: "${0} - ${1}",
+ unsorted: "Не сортировать этот столбец",
+ indirectSelectionRadio: "Строка ${0}, один выбор, радиокнопка",
+ indirectSelectionCheckBox: "Строка ${0}, несколько выборов, переключатель",
+ selectAll: "Выбрать все"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/ru/Filter.js b/js/dojo/dojox/grid/enhanced/nls/ru/Filter.js
new file mode 100644
index 0000000..ea9567d
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ru/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ru/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Удалить фильтр",
+ "filterDefDialogTitle": "Фильтр",
+ "ruleTitleTemplate": "Правило ${0}",
+
+ "conditionEqual": "равно",
+ "conditionNotEqual": "не равно",
+ "conditionLess": "меньше, чем",
+ "conditionLessEqual": "меньше или равно",
+ "conditionLarger": "больше, чем",
+ "conditionLargerEqual": "больше или равно",
+ "conditionContains": "содержит",
+ "conditionIs": "является",
+ "conditionStartsWith": "начинается с",
+ "conditionEndWith": "заканчивается на",
+ "conditionNotContain": "не содержит",
+ "conditionIsNot": "не является",
+ "conditionNotStartWith": "не начинается с",
+ "conditionNotEndWith": "не заканчивается на",
+ "conditionBefore": "до",
+ "conditionAfter": "после",
+ "conditionRange": "диапазон",
+ "conditionIsEmpty": "пустое",
+
+ "all": "все",
+ "any": "любое",
+ "relationAll": "все правила",
+ "waiRelAll": "Соответствие всем следующим правилам:",
+ "relationAny": "любое правило",
+ "waiRelAny": "Соответствие любому из следующих правил:",
+ "relationMsgFront": "Соответствие",
+ "relationMsgTail": "",
+ "and": "и",
+ "or": "или",
+
+ "addRuleButton": "Добавить правило",
+ "waiAddRuleButton": "Добавить новое правило",
+ "removeRuleButton": "Удалить правило",
+ "waiRemoveRuleButtonTemplate": "Удалить правило ${0}",
+
+ "cancelButton": "Отмена",
+ "waiCancelButton": "Отменить этот диалог",
+ "clearButton": "Удалить",
+ "waiClearButton": "Удалить фильтр",
+ "filterButton": "Фильтр",
+ "waiFilterButton": "Передать фильтр",
+
+ "columnSelectLabel": "Столбец",
+ "waiColumnSelectTemplate": "Столбец для правила ${0}",
+ "conditionSelectLabel": "Условие",
+ "waiConditionSelectTemplate": "Условие для правила ${0}",
+ "valueBoxLabel": "Значение",
+ "waiValueBoxTemplate": "Задайте значение фильтра для правила ${0}",
+
+ "rangeTo": "до",
+ "rangeTemplate": "от ${0} до ${1}",
+
+ "statusTipHeaderColumn": "Столбец",
+ "statusTipHeaderCondition": "Правила",
+ "statusTipTitle": "Панель фильтра",
+ "statusTipMsg": "Щелкните по панели фильтра, чтобы применить фильтр к значениям в ${0}.",
+ "anycolumn": "любой столбец",
+ "statusTipTitleNoFilter": "Панель фильтра",
+ "statusTipTitleHasFilter": "Фильтр",
+ "statusTipRelAny": "Соответствует любому из правил.",
+ "statusTipRelAll": "Соответствует всем правилам.",
+
+ "defaultItemsName": "элементов",
+ "filterBarMsgHasFilterTemplate": "Показано ${0} из ${1} ${2}.",
+ "filterBarMsgNoFilterTemplate": "Фильтр не применен",
+
+ "filterBarDefButton": "Задать фильтр",
+ "waiFilterBarDefButton": "Применить фильтр к таблице",
+ "a11yFilterBarDefButton": "Фильтр...",
+ "filterBarClearButton": "Удалить фильтр",
+ "waiFilterBarClearButton": "Удалить фильтр",
+ "closeFilterBarBtn": "Закрыть панель фильтра",
+
+ "clearFilterMsg": "Фильтр будет удален, и будут показаны все записи.",
+ "anyColumnOption": "Любой столбец",
+
+ "trueLabel": "True",
+ "falseLabel": "False"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/ru/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/ru/Pagination.js
new file mode 100644
index 0000000..db662ca
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/ru/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/ru/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} из ${1} ${0}",
+ "firstTip": "Первая страница",
+ "lastTip": "Последняя страница",
+ "nextTip": "Следующая страница",
+ "prevTip": "Предыдущая страница",
+ "itemTitle": "элементов",
+ "singularItemTitle": "элемент",
+ "pageStepLabelTemplate": "Страница ${0}",
+ "pageSizeLabelTemplate": "${0} элементов на странице",
+ "allItemsLabelTemplate": "Все элементы",
+ "gotoButtonTitle": "Перейти на определенную страницу",
+ "dialogTitle": "Перейти на страницу",
+ "dialogIndication": "Задайте номер страницы",
+ "pageCountIndication": " (${0} страниц)",
+ "dialogConfirm": "Перейти",
+ "dialogCancel": "Отмена",
+ "all": "все"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/sk/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/sk/EnhancedGrid.js
new file mode 100644
index 0000000..9338e81
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/sk/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/sk/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Jednoduché triedenie",
+ nestedSort: "Vnorené triedenie",
+ ascending: "Vzostupne",
+ descending: "Zostupne",
+ sortingState: "${0} - ${1}",
+ unsorted: "Netriediť tento stĺpec",
+ indirectSelectionRadio: "Riadok ${0}, jednoduchý výber, prepínač",
+ indirectSelectionCheckBox: "Riadok ${0}, viacnásobný výber, začiarkavacie políčko",
+ selectAll: "Vybrať všetko"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/sk/Filter.js b/js/dojo/dojox/grid/enhanced/nls/sk/Filter.js
new file mode 100644
index 0000000..8d83150
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/sk/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/sk/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Zrušiť filter",
+ "filterDefDialogTitle": "Filter",
+ "ruleTitleTemplate": "Pravidlo ${0}",
+
+ "conditionEqual": "rovné",
+ "conditionNotEqual": "nerovné",
+ "conditionLess": "menšie ako",
+ "conditionLessEqual": "menšie ako alebo rovné",
+ "conditionLarger": "väčšie ako",
+ "conditionLargerEqual": "väčšie ako alebo rovné",
+ "conditionContains": "obsahuje",
+ "conditionIs": "je",
+ "conditionStartsWith": "začína s",
+ "conditionEndWith": "končí s",
+ "conditionNotContain": "neobsahuje",
+ "conditionIsNot": "nie je",
+ "conditionNotStartWith": "nezačína s",
+ "conditionNotEndWith": "nekončí s",
+ "conditionBefore": "pred",
+ "conditionAfter": "za",
+ "conditionRange": "rozsah",
+ "conditionIsEmpty": "je prázdne",
+
+ "all": "všetko",
+ "any": "žiadne",
+ "relationAll": "všetky pravidlá",
+ "waiRelAll": "Vyhovovať všetkým týmto pravidlám:",
+ "relationAny": "ľubovoľné pravidlá",
+ "waiRelAny": "Vyhovovať ľubovoľným z týchto pravidiel:",
+ "relationMsgFront": "Vyhovieť",
+ "relationMsgTail": "",
+ "and": "a",
+ "or": "alebo",
+
+ "addRuleButton": "Pridať pravidlo",
+ "waiAddRuleButton": "Pridať nové pravidlo",
+ "removeRuleButton": "Odstrániť pravidlo",
+ "waiRemoveRuleButtonTemplate": "Odstrániť pravidlo ${0}",
+
+ "cancelButton": "Zrušiť",
+ "waiCancelButton": "Zrušiť toto dialógové okno",
+ "clearButton": "Zrušiť",
+ "waiClearButton": "Zrušiť filter",
+ "filterButton": "Filtrovať",
+ "waiFilterButton": "Odoslať filter",
+
+ "columnSelectLabel": "Stĺpec",
+ "waiColumnSelectTemplate": "Stĺpec pre pravidlo ${0}",
+ "conditionSelectLabel": "Podmienka",
+ "waiConditionSelectTemplate": "Podmienka pre pravidlo ${0}",
+ "valueBoxLabel": "Hodnota",
+ "waiValueBoxTemplate": "Zadajte hodnotu na filtrovanie pre pravidlo ${0}",
+
+ "rangeTo": "do",
+ "rangeTemplate": "od ${0} do ${1}",
+
+ "statusTipHeaderColumn": "Stĺpec",
+ "statusTipHeaderCondition": "Pravidlá",
+ "statusTipTitle": "Lišta filtra",
+ "statusTipMsg": "Kliknite na lištu filtra, ak chcete filtrovať podľa hodnôt v ${0}.",
+ "anycolumn": "ľubovoľný stĺpec",
+ "statusTipTitleNoFilter": "Lišta filtra",
+ "statusTipTitleHasFilter": "Filter",
+ "statusTipRelAny": "Zhoda s akýmikoľvek pravidlami.",
+ "statusTipRelAll": "Zhoda so všetkými pravidlami.",
+
+ "defaultItemsName": "položky",
+ "filterBarMsgHasFilterTemplate": "Zobrazuje sa ${0} z ${1} ${2}.",
+ "filterBarMsgNoFilterTemplate": "Nepoužíva sa žiadny filter",
+
+ "filterBarDefButton": "Definovať filter",
+ "waiFilterBarDefButton": "Filtrovať tabuľku",
+ "a11yFilterBarDefButton": "Filtrovať...",
+ "filterBarClearButton": "Zrušiť filter",
+ "waiFilterBarClearButton": "Zrušiť filter",
+ "closeFilterBarBtn": "Zatvoriť lištu filtra",
+
+ "clearFilterMsg": "Toto odstráni filter a zobrazí všetky dostupné záznamy",
+ "anyColumnOption": "Ľubovoľný stĺpec",
+
+ "trueLabel": "Pravda",
+ "falseLabel": "Nepravda"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/sk/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/sk/Pagination.js
new file mode 100644
index 0000000..ec6cb2e
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/sk/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/sk/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} z ${1} ${0}",
+ "firstTip": "Prvá strana",
+ "lastTip": "Posledná strana",
+ "nextTip": "Ďalšia strana",
+ "prevTip": "Predošlá strana",
+ "itemTitle": "položiek",
+ "singularItemTitle": "položka",
+ "pageStepLabelTemplate": "Strana ${0}",
+ "pageSizeLabelTemplate": "${0} položiek na strane",
+ "allItemsLabelTemplate": "Všetky položky",
+ "gotoButtonTitle": "Prejsť na špecifickú stranu",
+ "dialogTitle": "Prejsť na stranu",
+ "dialogIndication": "Zadajte číslo strany",
+ "pageCountIndication": " (${0} strán)",
+ "dialogConfirm": "Prejsť",
+ "dialogCancel": "Zrušiť",
+ "all": "všetko"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/sl/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/sl/EnhancedGrid.js
new file mode 100644
index 0000000..f2a3d6c
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/sl/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/sl/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Enostavno razvrščanje",
+ nestedSort: "Ugnezdeno razvrščanje",
+ ascending: "Naraščajoče",
+ descending: "Padajoče",
+ sortingState: "${0} - ${1}",
+ unsorted: "Ne razvrščaj tega stolpca",
+ indirectSelectionRadio: "Vrstica ${0}, izbira enega elementa, okence z izbirnim gumbom",
+ indirectSelectionCheckBox: "Vrstica ${0}, izbira več elementov, okence s potrditvenimi polji",
+ selectAll: "Izberi vse"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/sl/Filter.js b/js/dojo/dojox/grid/enhanced/nls/sl/Filter.js
new file mode 100644
index 0000000..283b9c7
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/sl/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/sl/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Počisti filter",
+ "filterDefDialogTitle": "Filter",
+ "ruleTitleTemplate": "Pravilo ${0}",
+
+ "conditionEqual": "je enako",
+ "conditionNotEqual": "ni enako",
+ "conditionLess": "je manjše kot",
+ "conditionLessEqual": "je manjše kot ali enako",
+ "conditionLarger": "je večje kot",
+ "conditionLargerEqual": "je večje kot ali enako",
+ "conditionContains": "vsebuje",
+ "conditionIs": "je",
+ "conditionStartsWith": "se začne s",
+ "conditionEndWith": "se konča s",
+ "conditionNotContain": "ne vsebuje",
+ "conditionIsNot": "ni",
+ "conditionNotStartWith": "se ne začne s",
+ "conditionNotEndWith": "se ne konča s",
+ "conditionBefore": "pred",
+ "conditionAfter": "za",
+ "conditionRange": "obseg",
+ "conditionIsEmpty": "je prazno",
+
+ "all": "vse",
+ "any": "karkoli",
+ "relationAll": "vsa pravila",
+ "waiRelAll": "Ujema se z vsemi od naslednjih pravil:",
+ "relationAny": "katerakoli pravila",
+ "waiRelAny": "Ujema se s katerimkoli od naslednjih pravil:",
+ "relationMsgFront": "Ujemanje",
+ "relationMsgTail": "",
+ "and": "in",
+ "or": "ali",
+
+ "addRuleButton": "Dodaj pravilo",
+ "waiAddRuleButton": "Dodaj novo pravilo",
+ "removeRuleButton": "Odstrani pravilo",
+ "waiRemoveRuleButtonTemplate": "Odstrani pravilo ${0}",
+
+ "cancelButton": "Prekliči",
+ "waiCancelButton": "Prekliči to pogovorno okno",
+ "clearButton": "Počisti",
+ "waiClearButton": "Počisti filter",
+ "filterButton": "Filter",
+ "waiFilterButton": "Predloži filter",
+
+ "columnSelectLabel": "Stolpec",
+ "waiColumnSelectTemplate": "Stolpec za pravilo ${0}",
+ "conditionSelectLabel": "Pogoj",
+ "waiConditionSelectTemplate": "Pogoj za pravilo ${0}",
+ "valueBoxLabel": "Vrednost",
+ "waiValueBoxTemplate": "Vnesite vrednost za filter pravila ${0}",
+
+ "rangeTo": "do",
+ "rangeTemplate": "od ${0} do ${1}",
+
+ "statusTipHeaderColumn": "Stolpec",
+ "statusTipHeaderCondition": "Pravila",
+ "statusTipTitle": "Vrstica za filtriranje",
+ "statusTipMsg": "Kliknite vrstico za filtriranje tukaj, da prefiltrirate vrednosti v ${0}.",
+ "anycolumn": "katerikoli stolpec",
+ "statusTipTitleNoFilter": "Vrstica za filtriranje",
+ "statusTipTitleHasFilter": "Filter",
+ "statusTipRelAny": "Ujemanje s katerimkoli pravilom.",
+ "statusTipRelAll": "Ujemanje z vsemi pravili.",
+
+ "defaultItemsName": "postavke",
+ "filterBarMsgHasFilterTemplate": "Prikazanih je ${0} od ${1} ${2}.",
+ "filterBarMsgNoFilterTemplate": "Uveljavljen ni noben filter.",
+
+ "filterBarDefButton": "Definiraj filter",
+ "waiFilterBarDefButton": "Filtriraj tabelo",
+ "a11yFilterBarDefButton": "Filtriraj ...",
+ "filterBarClearButton": "Počisti filter",
+ "waiFilterBarClearButton": "Počisti filter",
+ "closeFilterBarBtn": "Zapri vrstico za filtriranje",
+
+ "clearFilterMsg": "S tem boste odstranili filter in prikazali se bodo vsi razpoložljivi zapisi.",
+ "anyColumnOption": "Katerikoli stolpec",
+
+ "trueLabel": "True",
+ "falseLabel": "False"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/sl/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/sl/Pagination.js
new file mode 100644
index 0000000..5ea9222
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/sl/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/sl/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} od ${1} ${0}",
+ "firstTip": "Prva stran",
+ "lastTip": "Zadnja stran",
+ "nextTip": "Naslednja stran",
+ "prevTip": "Prejšnja stran",
+ "itemTitle": "postavke",
+ "singularItemTitle": "postavka",
+ "pageStepLabelTemplate": "Stran ${0}",
+ "pageSizeLabelTemplate": "${0} postavk na stran",
+ "allItemsLabelTemplate": "Vse postavke",
+ "gotoButtonTitle": "Pojdi na specifično stran",
+ "dialogTitle": "Pojdi na stran",
+ "dialogIndication": "Podajte številko strani",
+ "pageCountIndication": " (${0} strani)",
+ "dialogConfirm": "Pojdi",
+ "dialogCancel": "Prekliči",
+ "all": "vse"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/sv/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/sv/EnhancedGrid.js
new file mode 100644
index 0000000..dd6d606
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/sv/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/sv/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Enkel sortering",
+ nestedSort: "Nästlad sortering",
+ ascending: "Stigande",
+ descending: "Fallande",
+ sortingState: "${0} - ${1}",
+ unsorted: "Sortera inte den här kolumnen",
+ indirectSelectionRadio: "Rad ${0}, ett enda val, alternativruta",
+ indirectSelectionCheckBox: "Rad ${0}, flera val, kryssruta",
+ selectAll: "Markera alla "
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/sv/Filter.js b/js/dojo/dojox/grid/enhanced/nls/sv/Filter.js
new file mode 100644
index 0000000..2a58c48
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/sv/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/sv/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Rensa filter",
+ "filterDefDialogTitle": "Filter",
+ "ruleTitleTemplate": "Regel ${0}",
+
+ "conditionEqual": "lika med",
+ "conditionNotEqual": "inte lika med",
+ "conditionLess": "är mindre än",
+ "conditionLessEqual": "mindre eller lika med",
+ "conditionLarger": "är större än",
+ "conditionLargerEqual": "större än eller lika med",
+ "conditionContains": "innehåller",
+ "conditionIs": "är",
+ "conditionStartsWith": "börjar med",
+ "conditionEndWith": "slutar med",
+ "conditionNotContain": "innehåller inte",
+ "conditionIsNot": "är inte",
+ "conditionNotStartWith": "börjar inte med",
+ "conditionNotEndWith": "slutar inte med",
+ "conditionBefore": "före",
+ "conditionAfter": "efter",
+ "conditionRange": "intervall",
+ "conditionIsEmpty": "är tom",
+
+ "all": "alla",
+ "any": "någon",
+ "relationAll": "alla regler",
+ "waiRelAll": "Matcha alla följande regler:",
+ "relationAny": "någon regel",
+ "waiRelAny": "Matcha någon av följande regler:",
+ "relationMsgFront": "Matcha",
+ "relationMsgTail": "",
+ "and": "och",
+ "or": "eller",
+
+ "addRuleButton": "Lägg till regel",
+ "waiAddRuleButton": "Lägg till en ny regel",
+ "removeRuleButton": "Ta bort regel",
+ "waiRemoveRuleButtonTemplate": "Ta bort regel ${0}",
+
+ "cancelButton": "Avbryt",
+ "waiCancelButton": "Avbryt dialogen",
+ "clearButton": "Rensa",
+ "waiClearButton": "Rensa filtret",
+ "filterButton": "Filtrera",
+ "waiFilterButton": "Filtrera",
+
+ "columnSelectLabel": "Kolumn",
+ "waiColumnSelectTemplate": "Kolumn för regel ${0}",
+ "conditionSelectLabel": "Villkor",
+ "waiConditionSelectTemplate": "Villkor för regel ${0}",
+ "valueBoxLabel": "Värde",
+ "waiValueBoxTemplate": "Ange värde för filtrering efter regeln ${0}",
+
+ "rangeTo": "till",
+ "rangeTemplate": "från ${0} till ${1}",
+
+ "statusTipHeaderColumn": "Kolumn",
+ "statusTipHeaderCondition": "Regler",
+ "statusTipTitle": "Filterfält",
+ "statusTipMsg": "Klicka på filterfältet om du vill filtrera värden i ${0}.",
+ "anycolumn": "alla kolumner",
+ "statusTipTitleNoFilter": "Filterfält",
+ "statusTipTitleHasFilter": "Filter",
+ "statusTipRelAny": "Matcha någon regel.",
+ "statusTipRelAll": "Matcha alla regler.",
+
+ "defaultItemsName": "objekt",
+ "filterBarMsgHasFilterTemplate": "${0} av ${1} ${2} visas.",
+ "filterBarMsgNoFilterTemplate": "Inget filter tillämpat",
+
+ "filterBarDefButton": "Definiera filter",
+ "waiFilterBarDefButton": "Filtrera tabellen",
+ "a11yFilterBarDefButton": "Filter...",
+ "filterBarClearButton": "Rensa filter",
+ "waiFilterBarClearButton": "Rensa filtret",
+ "closeFilterBarBtn": "Stäng filterfält",
+
+ "clearFilterMsg": "Tar bort filtret och visar alla tillgängliga poster.",
+ "anyColumnOption": "Alla kolumner",
+
+ "trueLabel": "Sant",
+ "falseLabel": "Falskt"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/sv/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/sv/Pagination.js
new file mode 100644
index 0000000..472d5e8
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/sv/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/sv/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} av ${1} ${0}",
+ "firstTip": "Första sidan",
+ "lastTip": "Sista sidan",
+ "nextTip": "Nästa sida",
+ "prevTip": "Föregående sida",
+ "itemTitle": "objekt",
+ "singularItemTitle": "objekt",
+ "pageStepLabelTemplate": "Sida ${0}",
+ "pageSizeLabelTemplate": "${0} objekt per sida",
+ "allItemsLabelTemplate": "Alla objekt",
+ "gotoButtonTitle": "Gå till en viss sida",
+ "dialogTitle": "Gå till sidan",
+ "dialogIndication": "Ange sidnummer",
+ "pageCountIndication": " (${0} sidor)",
+ "dialogConfirm": "Gå",
+ "dialogCancel": "Avbryt",
+ "all": "alla"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/th/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/th/EnhancedGrid.js
new file mode 100644
index 0000000..d0bd82c
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/th/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/th/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "เรียงลำดับแบบเดี่ยว",
+ nestedSort: "เรียงลำดับที่ซับซ้อน",
+ ascending: "จากน้อยไปหามาก",
+ descending: "จากมากไปหาน้อย",
+ sortingState: "${0} - ${1}",
+ unsorted: "ห้ามเรียงลำดับคอลัมน์นี้",
+ indirectSelectionRadio: "แถว ${0}, การเลือกเดียว, กล่องวิทยุ",
+ indirectSelectionCheckBox: "แถว ${0}, การเลือกจำนวนมาก, เช็กบ็อกซ์",
+ selectAll: "เลือกทั้งหมด"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/th/Filter.js b/js/dojo/dojox/grid/enhanced/nls/th/Filter.js
new file mode 100644
index 0000000..cb3f948
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/th/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/th/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "ลบตัวกรอง",
+ "filterDefDialogTitle": "ตัวกรอง",
+ "ruleTitleTemplate": "กฏ ${0}",
+
+ "conditionEqual": "เท่ากับ",
+ "conditionNotEqual": "ไม่เท่ากับ",
+ "conditionLess": "น้อยกว่า",
+ "conditionLessEqual": "น้อยกว่าหรือเท่ากับ",
+ "conditionLarger": "มากกว่า",
+ "conditionLargerEqual": "มากกว่าหรือเท่ากับ",
+ "conditionContains": "ประกอบด้วย",
+ "conditionIs": "เป็น",
+ "conditionStartsWith": "เริ่มต้นด้วย",
+ "conditionEndWith": "ลงท้ายด้วย",
+ "conditionNotContain": "ไม่ประกอบด้วย",
+ "conditionIsNot": "ไม่",
+ "conditionNotStartWith": "ไม่เริ่มต้นด้วย",
+ "conditionNotEndWith": "ไม่ลงท้ายด้วย",
+ "conditionBefore": "ก่อน",
+ "conditionAfter": "หลัง",
+ "conditionRange": "ช่วง",
+ "conditionIsEmpty": "ว่างอยู่",
+
+ "all": "ทั้งหมด",
+ "any": "ใด",
+ "relationAll": "กฏทั้งหมด",
+ "waiRelAll": "ตรงกับกฏทั้งหมดต่อไปนี้:",
+ "relationAny": "กฏใดๆ",
+ "waiRelAny": "ตรงกับกฏใดๆต่อไปนี้:",
+ "relationMsgFront": "ตรงกับ",
+ "relationMsgTail": "",
+ "and": "และ",
+ "or": "หรือ",
+
+ "addRuleButton": "เพิ่มกฏ",
+ "waiAddRuleButton": "เพิ่มกฏใหม่",
+ "removeRuleButton": "ลบกฏ",
+ "waiRemoveRuleButtonTemplate": "ลบกฏ ${0}",
+
+ "cancelButton": "ยกเลิก",
+ "waiCancelButton": "ยกเลิกไดอะล็อกนี้",
+ "clearButton": "ลบ",
+ "waiClearButton": "ลบตัวกรอง",
+ "filterButton": "ตัวกรอง",
+ "waiFilterButton": "ส่งตัวกรอง",
+
+ "columnSelectLabel": "คอลัมน์",
+ "waiColumnSelectTemplate": "คอลัมน์สำหรับกฏ ${0}",
+ "conditionSelectLabel": "เงื่อนไข",
+ "waiConditionSelectTemplate": "เงื่อนไขสำหรับกฏ ${0}",
+ "valueBoxLabel": "ค่า",
+ "waiValueBoxTemplate": "ป้อนค่าให้กับตัวกรองสำหรับกฏ ${0}",
+
+ "rangeTo": "ถึง",
+ "rangeTemplate": "จาก ${0} ถึง ${1}",
+
+ "statusTipHeaderColumn": "คอลัมน์",
+ "statusTipHeaderCondition": "กฏ",
+ "statusTipTitle": "แถบตัวกรอง",
+ "statusTipMsg": "คลิกที่แถบตัวกรองที่นี่เพื่อกรองค่าใน ${0}",
+ "anycolumn": "คอลัมน์ใดๆ",
+ "statusTipTitleNoFilter": "แถบตัวกรอง",
+ "statusTipTitleHasFilter": "ตัวกรอง",
+ "statusTipRelAny": "ตรงกับกฏใดๆ",
+ "statusTipRelAll": "ตรงกับทุกกฏ",
+
+ "defaultItemsName": "ไอเท็ม",
+ "filterBarMsgHasFilterTemplate": "${0} ของ ${1} ${2} จะถูกแสดง",
+ "filterBarMsgNoFilterTemplate": "ไม่นำตัวกรองไปใช้",
+
+ "filterBarDefButton": "กำหนดตัวกรอง",
+ "waiFilterBarDefButton": "กรองตาราง",
+ "a11yFilterBarDefButton": "ตัวกรอง...",
+ "filterBarClearButton": "ลบตัวกรอง",
+ "waiFilterBarClearButton": "ลบตัวกรอง",
+ "closeFilterBarBtn": "ปิดแถบตัวกรอง",
+
+ "clearFilterMsg": "ซึ่งจะลบตัวกรองออกและแสดงเร็กคอร์ดที่พร้อมใช้งานทั้งหมด",
+ "anyColumnOption": "คอลัมน์ใดๆ",
+
+ "trueLabel": "จริง",
+ "falseLabel": "เท็จ"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/th/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/th/Pagination.js
new file mode 100644
index 0000000..b3d536e
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/th/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/th/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} จาก ${1} ${0}",
+ "firstTip": "หน้าแรก",
+ "lastTip": "หน้าสุดท้าย",
+ "nextTip": "หน้าถัดไป",
+ "prevTip": "หน้าก่อนหน้านี้",
+ "itemTitle": "ไอเท็ม",
+ "singularItemTitle": "ไอเท็ม",
+ "pageStepLabelTemplate": "หน้า ${0}",
+ "pageSizeLabelTemplate": "${0} ไอเท็มต่อหน้า",
+ "allItemsLabelTemplate": "รายการ ทั้งหมด",
+ "gotoButtonTitle": "ไปที่หน้าที่ระบุ",
+ "dialogTitle": "ไปที่หน้า",
+ "dialogIndication": "ระบุหมายเลขหน้า",
+ "pageCountIndication": " (${0} หน้า)",
+ "dialogConfirm": "ไปที่",
+ "dialogCancel": "ยกเลิก",
+ "all": "ทั้งหมด"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/tr/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/tr/EnhancedGrid.js
new file mode 100644
index 0000000..78c566b
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/tr/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/tr/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "Tekli Sıralama",
+ nestedSort: "İç İçe Sıralama",
+ ascending: "Artan Düzende",
+ descending: "Azalan Düzende",
+ sortingState: "${0} - ${1}",
+ unsorted: "Bu sütunu sıralama",
+ indirectSelectionRadio: "Satır ${0}, tek seçimli, radyo düğmesi",
+ indirectSelectionCheckBox: "Satır ${0}, çok seçimli, radyo düğmesi",
+ selectAll: "Tümünü seç"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/tr/Filter.js b/js/dojo/dojox/grid/enhanced/nls/tr/Filter.js
new file mode 100644
index 0000000..06ed5e7
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/tr/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/tr/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "Süzgeci Kaldır",
+ "filterDefDialogTitle": "Süzgeç",
+ "ruleTitleTemplate": "Kural ${0}",
+
+ "conditionEqual": "eşittir",
+ "conditionNotEqual": "eşit değildir",
+ "conditionLess": "küçüktür",
+ "conditionLessEqual": "küçüktür veya eşittir",
+ "conditionLarger": "büyüktür",
+ "conditionLargerEqual": "büyüktür veya eşittir",
+ "conditionContains": "içerir",
+ "conditionIs": "şudur",
+ "conditionStartsWith": "şununla başlar",
+ "conditionEndWith": "şununla biter",
+ "conditionNotContain": "içermez",
+ "conditionIsNot": "şu değildir",
+ "conditionNotStartWith": "şununla başlamaz",
+ "conditionNotEndWith": "şununla bitmez",
+ "conditionBefore": "önce",
+ "conditionAfter": "sonra",
+ "conditionRange": "aralık",
+ "conditionIsEmpty": "boş",
+
+ "all": "tümü",
+ "any": "herhangi biri",
+ "relationAll": "tüm kurallar",
+ "waiRelAll": "Aşağıdaki tüm kurallarla eşleştir",
+ "relationAny": "kuralların herhangi biri",
+ "waiRelAny": "Aşağıdaki kuralların herhangi biri ile eşleştir",
+ "relationMsgFront": "Eşleştir",
+ "relationMsgTail": "",
+ "and": "ve",
+ "or": "veya",
+
+ "addRuleButton": "Kural Ekle",
+ "waiAddRuleButton": "Yeni bir kural ekle",
+ "removeRuleButton": "Kuralı Kaldır",
+ "waiRemoveRuleButtonTemplate": "${0} kuralını kaldır",
+
+ "cancelButton": "İptal",
+ "waiCancelButton": "Bu iletişim kutusunu iptal et",
+ "clearButton": "Kaldır",
+ "waiClearButton": "Süzgeci kaldır",
+ "filterButton": "Süzgeç",
+ "waiFilterButton": "Süzgeci gönder",
+
+ "columnSelectLabel": "Sütun",
+ "waiColumnSelectTemplate": "${0} kuralı için sütun",
+ "conditionSelectLabel": "Koşul",
+ "waiConditionSelectTemplate": "${0} kuralı için koşul",
+ "valueBoxLabel": "Değer",
+ "waiValueBoxTemplate": "${0} kuralı için süzülecek değeri girin",
+
+ "rangeTo": "bitiş",
+ "rangeTemplate": "${0} - ${1}",
+
+ "statusTipHeaderColumn": "Sütun",
+ "statusTipHeaderCondition": "Kurallar",
+ "statusTipTitle": "Süzgeç Çubuğu",
+ "statusTipMsg": "${0} içindeki değerlere göre süzmek için burada süzgeç çubuğunu tıklatın.",
+ "anycolumn": "herhangi bir sütun",
+ "statusTipTitleNoFilter": "Süzgeç Çubuğu",
+ "statusTipTitleHasFilter": "Süzgeç",
+ "statusTipRelAny": "Herhangi bir kuralı eşleştir.",
+ "statusTipRelAll": "Bütün kuralları eşleştir.",
+
+ "defaultItemsName": "öğe",
+ "filterBarMsgHasFilterTemplate": "${0} / ${1} ${2} gösteriliyor.",
+ "filterBarMsgNoFilterTemplate": "Süzgeç uygulanmadı",
+
+ "filterBarDefButton": "Süzgeç tanımla",
+ "waiFilterBarDefButton": "Tabloyu süz",
+ "a11yFilterBarDefButton": "Süz...",
+ "filterBarClearButton": "Süzgeci kaldır",
+ "waiFilterBarClearButton": "Süzgeci kaldır",
+ "closeFilterBarBtn": "Süzgeç çubuğunu kapat",
+
+ "clearFilterMsg": "Bu seçenek süzgeci kaldırır ve tüm kullanılabilir kayıtları gösterir.",
+ "anyColumnOption": "Herhangi Bir Sütun",
+
+ "trueLabel": "Doğru",
+ "falseLabel": "Yanlış"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/tr/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/tr/Pagination.js
new file mode 100644
index 0000000..94eb9a2
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/tr/Pagination.js
@@ -0,0 +1,24 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/tr/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} / ${1} ${0}",
+ "firstTip": "İlk Sayfa",
+ "lastTip": "Son Sayfa",
+ "nextTip": "Sonraki Sayfa",
+ "prevTip": "Önceki Sayfa",
+ "itemTitle": "öğe",
+ "singularItemTitle": "öğe",
+ "pageStepLabelTemplate": "Sayfa ${0}",
+ "pageSizeLabelTemplate": "Sayfa başına ${0} öğe",
+ "allItemsLabelTemplate": "Tüm öğeler",
+ "gotoButtonTitle": "Belirli bir sayfaya git",
+ "dialogTitle": "Sayfaya Git",
+ "dialogIndication": "Sayfa numarasını belirtin",
+ "pageCountIndication": " (${0} sayfa)",
+ "dialogConfirm": "Git",
+ "dialogCancel": "İptal",
+ "all": "tümü"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/zh-tw/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/zh-tw/EnhancedGrid.js
new file mode 100644
index 0000000..d25ffdb
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/zh-tw/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/zh-tw/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "單一排序",
+ nestedSort: "巢狀排序",
+ ascending: "遞增",
+ descending: "降冪",
+ sortingState: "${0} - ${1}",
+ unsorted: "請勿對此欄執行排序",
+ indirectSelectionRadio: "第 ${0} 行,單一選項,圓鈕框",
+ indirectSelectionCheckBox: "第 ${0} 行,多重選項,勾選框",
+ selectAll: "全選"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/zh-tw/Filter.js b/js/dojo/dojox/grid/enhanced/nls/zh-tw/Filter.js
new file mode 100644
index 0000000..4488b78
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/zh-tw/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/zh-tw/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "清除過濾器",
+ "filterDefDialogTitle": "過濾器",
+ "ruleTitleTemplate": "規則 ${0}",
+
+ "conditionEqual": "等於",
+ "conditionNotEqual": "不等於",
+ "conditionLess": "是小於",
+ "conditionLessEqual": "小於或等於",
+ "conditionLarger": "是大於",
+ "conditionLargerEqual": "大於或等於",
+ "conditionContains": "內容",
+ "conditionIs": "是",
+ "conditionStartsWith": "開始於",
+ "conditionEndWith": "結束於",
+ "conditionNotContain": "不包含",
+ "conditionIsNot": "不是",
+ "conditionNotStartWith": "不開始於",
+ "conditionNotEndWith": "不結束於",
+ "conditionBefore": "之前",
+ "conditionAfter": "之後",
+ "conditionRange": "範圍",
+ "conditionIsEmpty": "為空",
+
+ "all": "全部",
+ "any": "任何",
+ "relationAll": "所有規則",
+ "waiRelAll": "符合下列所有規則:",
+ "relationAny": "任何規則",
+ "waiRelAny": "符合下列任何規則:",
+ "relationMsgFront": "符合",
+ "relationMsgTail": "",
+ "and": "和",
+ "or": "或",
+
+ "addRuleButton": "新增規則",
+ "waiAddRuleButton": "新增規則",
+ "removeRuleButton": "移除規則",
+ "waiRemoveRuleButtonTemplate": "移除規則 ${0}",
+
+ "cancelButton": "取消",
+ "waiCancelButton": "取消此對話",
+ "clearButton": "清除",
+ "waiClearButton": "清除過濾器",
+ "filterButton": "過濾器",
+ "waiFilterButton": "提交過濾器",
+
+ "columnSelectLabel": "直欄",
+ "waiColumnSelectTemplate": "規則 ${0} 的直欄",
+ "conditionSelectLabel": "條件",
+ "waiConditionSelectTemplate": "規則 ${0} 的條件",
+ "valueBoxLabel": "值",
+ "waiValueBoxTemplate": "輸入要針對規則 ${0} 過濾的值",
+
+ "rangeTo": "至",
+ "rangeTemplate": "從 ${0} 至 ${1}",
+
+ "statusTipHeaderColumn": "直欄",
+ "statusTipHeaderCondition": "規則",
+ "statusTipTitle": "過濾器列",
+ "statusTipMsg": "按一下這裡的過濾器列以過濾 ${0} 中的值。",
+ "anycolumn": "任何直欄",
+ "statusTipTitleNoFilter": "過濾器列",
+ "statusTipTitleHasFilter": "過濾器",
+ "statusTipRelAny": "符合任何規則。",
+ "statusTipRelAll": "符合所有規則。",
+
+ "defaultItemsName": "項目",
+ "filterBarMsgHasFilterTemplate": "顯示 ${1} ${2} 之 ${0}。",
+ "filterBarMsgNoFilterTemplate": "未套用過濾器",
+
+ "filterBarDefButton": "定義過濾器",
+ "waiFilterBarDefButton": "過濾表格",
+ "a11yFilterBarDefButton": "過濾器...",
+ "filterBarClearButton": "清除過濾器",
+ "waiFilterBarClearButton": "清除過濾器",
+ "closeFilterBarBtn": "關閉過濾器列",
+
+ "clearFilterMsg": "這將會移除過濾器並顯示所有的可用記錄。",
+ "anyColumnOption": "任何直欄",
+
+ "trueLabel": "True",
+ "falseLabel": "False"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/zh-tw/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/zh-tw/Pagination.js
new file mode 100644
index 0000000..8f29af0
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/zh-tw/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/zh-tw/Pagination", //begin v1.x content
+({
+ "descTemplate": "${2} - ${3} / ${1} ${0}",
+ "firstTip": "首頁",
+ "lastTip": "末頁",
+ "nextTip": "下一頁",
+ "prevTip": "上一頁",
+ "itemTitle": "項目",
+ "singularItemTitle": "項目",
+ "pageStepLabelTemplate": "第 ${0} 頁",
+ "pageSizeLabelTemplate": "每頁 ${0} 個項目",
+ "allItemsLabelTemplate": "所有項目",
+ "gotoButtonTitle": "跳至特定頁面",
+ "dialogTitle": "跳至頁面",
+ "dialogIndication": "指定頁碼",
+ "pageCountIndication": "(${0} 頁)",
+ "dialogConfirm": "執行",
+ "dialogCancel": "取消",
+ "all": "全部"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/zh/EnhancedGrid.js b/js/dojo/dojox/grid/enhanced/nls/zh/EnhancedGrid.js
new file mode 100644
index 0000000..6494ae4
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/zh/EnhancedGrid.js
@@ -0,0 +1,17 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/zh/EnhancedGrid", //begin v1.x content
+({
+ singleSort: "单层排序",
+ nestedSort: "嵌套排序",
+ ascending: "升序",
+ descending: "降序",
+ sortingState: "${0} - ${1}",
+ unsorted: "请勿对此列进行排序",
+ indirectSelectionRadio: "第 ${0} 行,单选,单选框",
+ indirectSelectionCheckBox: "第 ${0} 行,多选,复选框",
+ selectAll: "全部选中"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/nls/zh/Filter.js b/js/dojo/dojox/grid/enhanced/nls/zh/Filter.js
new file mode 100644
index 0000000..f0f9f2b
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/zh/Filter.js
@@ -0,0 +1,89 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/zh/Filter", //begin v1.x content
+({
+ "clearFilterDialogTitle": "清除过滤器",
+ "filterDefDialogTitle": "过滤器",
+ "ruleTitleTemplate": "规则 ${0}",
+
+ "conditionEqual": "等于",
+ "conditionNotEqual": "不等于",
+ "conditionLess": "小于",
+ "conditionLessEqual": "小于或等于",
+ "conditionLarger": "大于",
+ "conditionLargerEqual": "大于或等于",
+ "conditionContains": "包含",
+ "conditionIs": "是",
+ "conditionStartsWith": "开始于",
+ "conditionEndWith": "结束于",
+ "conditionNotContain": "不包含",
+ "conditionIsNot": "非",
+ "conditionNotStartWith": "不是开始于",
+ "conditionNotEndWith": "不是结束于",
+ "conditionBefore": "先于",
+ "conditionAfter": "后于",
+ "conditionRange": "范围",
+ "conditionIsEmpty": "为空",
+
+ "all": "全部",
+ "any": "任何",
+ "relationAll": "所有规则",
+ "waiRelAll": "符合以下所有规则:",
+ "relationAny": "任何规则",
+ "waiRelAny": "符合以下任何规则:",
+ "relationMsgFront": "符合",
+ "relationMsgTail": "",
+ "and": "和",
+ "or": "或",
+
+ "addRuleButton": "添加规则",
+ "waiAddRuleButton": "添加新规则",
+ "removeRuleButton": "除去规则",
+ "waiRemoveRuleButtonTemplate": "除去规则 ${0}",
+
+ "cancelButton": "取消",
+ "waiCancelButton": "取消该对话",
+ "clearButton": "清除",
+ "waiClearButton": "清除过滤器",
+ "filterButton": "过滤器",
+ "waiFilterButton": "提交过滤器",
+
+ "columnSelectLabel": "列",
+ "waiColumnSelectTemplate": "规则 ${0} 的列",
+ "conditionSelectLabel": "条件",
+ "waiConditionSelectTemplate": "规则 ${0} 的条件",
+ "valueBoxLabel": "值",
+ "waiValueBoxTemplate": "将规则 ${0} 的值输入过滤器",
+
+ "rangeTo": "到",
+ "rangeTemplate": "从 ${0} 到 ${1}",
+
+ "statusTipHeaderColumn": "列",
+ "statusTipHeaderCondition": "规则",
+ "statusTipTitle": "过滤器栏",
+ "statusTipMsg": "单击此处的过滤器栏以过滤 ${0} 中的值。",
+ "anycolumn": "任何列",
+ "statusTipTitleNoFilter": "过滤器栏",
+ "statusTipTitleHasFilter": "过滤器",
+ "statusTipRelAny": "与任何规则匹配。",
+ "statusTipRelAll": "与所有规则匹配。",
+
+ "defaultItemsName": "项目",
+ "filterBarMsgHasFilterTemplate": "显示的 ${1} ${2} 的 ${0}。",
+ "filterBarMsgNoFilterTemplate": "未使用过滤器",
+
+ "filterBarDefButton": "定义过滤器",
+ "waiFilterBarDefButton": "过滤表",
+ "a11yFilterBarDefButton": "过滤器...",
+ "filterBarClearButton": "清除过滤器",
+ "waiFilterBarClearButton": "清除过滤器",
+ "closeFilterBarBtn": "关闭过滤器栏",
+
+ "clearFilterMsg": "该操作将除去过滤器并显示所有现有记录。",
+ "anyColumnOption": "任何列",
+
+ "trueLabel": "True",
+ "falseLabel": "False"
+})
+//end v1.x content
+);
diff --git a/js/dojo/dojox/grid/enhanced/nls/zh/Pagination.js b/js/dojo/dojox/grid/enhanced/nls/zh/Pagination.js
new file mode 100644
index 0000000..1e1b5c6
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/nls/zh/Pagination.js
@@ -0,0 +1,25 @@
+//>>built
+define(
+"dojox/grid/enhanced/nls/zh/Pagination", //begin v1.x content
+({
+ "descTemplate": "${1} 个${0}中的 ${2} - ${3}",
+ "firstTip": "第一页",
+ "lastTip": "最后一页",
+ "nextTip": "下一页",
+ "prevTip": "上一页",
+ "itemTitle": "项目",
+ "singularItemTitle": "项",
+ "pageStepLabelTemplate": "第 ${0} 页",
+ "pageSizeLabelTemplate": "每页的 ${0} 项目",
+ "allItemsLabelTemplate": "所有项目",
+ "gotoButtonTitle": "转到指定页面",
+ "dialogTitle": "转到页面",
+ "dialogIndication": "指定页数",
+ "pageCountIndication": "(${0} 页)",
+ "dialogConfirm": "确定",
+ "dialogCancel": "取消",
+ "all": "全部"
+})
+//end v1.x content
+);
+
diff --git a/js/dojo/dojox/grid/enhanced/plugins/AutoScroll.js b/js/dojo/dojox/grid/enhanced/plugins/AutoScroll.js
new file mode 100644
index 0000000..0dcb466
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/AutoScroll.js
@@ -0,0 +1,182 @@
+//>>built
+define("dojox/grid/enhanced/plugins/AutoScroll", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/lang",
+ "dojo/_base/html",
+ "dojo/_base/window",
+ "../_Plugin",
+ "../../_RowSelector",
+ "../../EnhancedGrid"
+], function(declare, array, lang, html, win, _Plugin, _RowSelector, EnhancedGrid){
+
+var AutoScroll = declare("dojox.grid.enhanced.plugins.AutoScroll", _Plugin, {
+ // summary:
+ // Provides horizontal and vertical auto-scroll for grid.
+
+ // name: String
+ // Plugin name
+ name: "autoScroll",
+
+ // autoScrollInterval: Integer
+ // The time interval (in miliseconds) between 2 scrolling.
+ autoScrollInterval: 1000,
+
+ // autoScrollMargin: Integer
+ // The width (in pixel) of the margin area where autoscroll can be triggered.
+ autoScrollMargin: 30,
+
+ constructor: function(grid, args){
+ this.grid = grid;
+ this.readyForAutoScroll = false;
+ this._scrolling = false;
+ args = lang.isObject(args) ? args : {};
+ if("interval" in args){
+ this.autoScrollInterval = args.interval;
+ }
+ if("margin" in args){
+ this.autoScrollMargin = args.margin;
+ }
+ this._initEvents();
+ this._mixinGrid();
+ },
+ _initEvents: function(){
+ var g = this.grid;
+ this.connect(g, "onCellMouseDown", function(){
+ this.readyForAutoScroll = true;
+ });
+ this.connect(g, "onHeaderCellMouseDown", function(){
+ this.readyForAutoScroll = true;
+ });
+ this.connect(g, "onRowSelectorMouseDown", function(){
+ this.readyForAutoScroll = true;
+ });
+ this.connect(win.doc, "onmouseup", function(evt){
+ this._manageAutoScroll(true);
+ this.readyForAutoScroll = false;
+ });
+ this.connect(win.doc, "onmousemove", function(evt){
+ if(this.readyForAutoScroll){
+ this._event = evt;
+ var gridPos = html.position(g.domNode),
+ hh = g._getHeaderHeight(),
+ margin = this.autoScrollMargin,
+ ey = evt.clientY, ex = evt.clientX,
+ gy = gridPos.y, gx = gridPos.x,
+ gh = gridPos.h, gw = gridPos.w;
+ if(ex >= gx && ex <= gx + gw){
+ if(ey >= gy + hh && ey < gy + hh + margin){
+ this._manageAutoScroll(false, true, false);
+ return;
+ }else if(ey > gy + gh - margin && ey <= gy + gh){
+ this._manageAutoScroll(false, true, true);
+ return;
+ }else if(ey >= gy && ey <= gy + gh){
+ var withinSomeview = array.some(g.views.views, function(view, i){
+ if(view instanceof _RowSelector){
+ return false;
+ }
+ var viewPos = html.position(view.domNode);
+ if(ex < viewPos.x + margin && ex >= viewPos.x){
+ this._manageAutoScroll(false, false, false, view);
+ return true;
+ }else if(ex > viewPos.x + viewPos.w - margin && ex < viewPos.x + viewPos.w){
+ this._manageAutoScroll(false, false, true, view);
+ return true;
+ }
+ return false;
+ }, this);
+ if(withinSomeview){
+ return;
+ }
+ }
+ }
+ //stop autoscroll.
+ this._manageAutoScroll(true);
+ }
+ });
+ },
+ _mixinGrid: function(){
+ var g = this.grid;
+ g.onStartAutoScroll = function(/*isVertical, isForward*/){};
+ g.onEndAutoScroll = function(/*isVertical, isForward, view, scrollToRowIndex, event*/){};
+ },
+ _fireEvent: function(eventName, args){
+ var g = this.grid;
+ switch(eventName){
+ case "start":
+ g.onStartAutoScroll.apply(g, args);
+ break;
+ case "end":
+ g.onEndAutoScroll.apply(g, args);
+ break;
+ }
+ },
+ _manageAutoScroll: function(toStop, isVertical, isForward, view){
+ if(toStop){
+ this._scrolling = false;
+ clearInterval(this._handler);
+ }else if(!this._scrolling){
+ this._scrolling = true;
+ this._fireEvent("start", [isVertical, isForward, view]);
+ this._autoScroll(isVertical, isForward, view);
+ this._handler = setInterval(lang.hitch(this, "_autoScroll", isVertical, isForward, view), this.autoScrollInterval);
+ }
+ },
+ _autoScroll: function(isVertical, isForward, view){
+ var g = this.grid,
+ target = null;
+ if(isVertical){
+ var targetRow = g.scroller.firstVisibleRow + (isForward ? 1 : -1);
+ if(targetRow >= 0 && targetRow < g.rowCount){
+ g.scrollToRow(targetRow);
+ target = targetRow;
+ }
+ }else{
+ target = this._scrollColumn(isForward, view);
+ }
+ if(target !== null){
+ this._fireEvent("end", [isVertical, isForward, view, target, this._event]);
+ }
+ },
+ _scrollColumn: function(isForward, view){
+ var node = view.scrollboxNode,
+ target = null;
+ if(node.clientWidth < node.scrollWidth){
+ var cells = array.filter(this.grid.layout.cells, function(cell){
+ return !cell.hidden;
+ });
+ var viewPos = html.position(view.domNode);
+ var limit, edge, headerPos, i;
+ if(isForward){
+ limit = node.clientWidth;
+ for(i = 0; i < cells.length; ++i){
+ headerPos = html.position(cells[i].getHeaderNode());
+ edge = headerPos.x - viewPos.x + headerPos.w;
+ if(edge > limit){
+ target = cells[i].index;
+ node.scrollLeft += edge - limit + 10;
+ break;
+ }
+ }
+ }else{
+ limit = 0;
+ for(i = cells.length - 1; i >= 0; --i){
+ headerPos = html.position(cells[i].getHeaderNode());
+ edge = headerPos.x - viewPos.x;
+ if(edge < limit){
+ target = cells[i].index;
+ node.scrollLeft += edge - limit - 10;
+ break;
+ }
+ }
+ }
+ }
+ return target;
+ }
+});
+
+EnhancedGrid.registerPlugin(AutoScroll);
+
+return AutoScroll;
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/CellMerge.js b/js/dojo/dojox/grid/enhanced/plugins/CellMerge.js
new file mode 100644
index 0000000..7284ace
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/CellMerge.js
@@ -0,0 +1,276 @@
+//>>built
+define("dojox/grid/enhanced/plugins/CellMerge", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/lang",
+ "dojo/_base/html",
+ "../_Plugin",
+ "../../EnhancedGrid"
+], function(declare, array, lang, html, _Plugin, EnhancedGrid){
+
+var CellMerge = declare("dojox.grid.enhanced.plugins.CellMerge", _Plugin, {
+ // summary:
+ // This plugin provides functions to merge(un-merge) adjacent cells within one row.
+ // Acceptable plugin paramters:
+ // 1. mergedCells: Array
+ // An array of objects with structure:
+ // {
+ // row: function(Integer)|Integer
+ // If it's a function, it's a predicate to decide which rows are to be merged.
+ // It takes an integer (the row index), and should return true or false;
+ // start: Integer
+ // The column index of the left most cell that shall be merged.
+ // end: Integer
+ // The column index of the right most cell that shall be merged.
+ // major: Integer
+ // The column index of the cell whose content should be used as the content of the merged cell.
+ // It must be larger than or equal to the startColumnIndex, and less than or equal to the endColumnIndex.
+ // If it is omitted, the content of the leading edge (left-most for ltr, right most for rtl) cell will be used.
+ // }
+
+ // name: String
+ // Plugin name
+ name: "cellMerge",
+
+ constructor: function(grid, args){
+ this.grid = grid;
+ this._records = [];
+ this._merged = {};
+ if(args && lang.isObject(args)){
+ this._setupConfig(args.mergedCells);
+ }
+ this._initEvents();
+ this._mixinGrid();
+ },
+ //----------------Public----------------------------
+ mergeCells: function(rowTester, startColumnIndex, endColumnIndex, majorColumnIndex){
+ // summary:
+ // Merge cells from *startColumnIndex* to *endColumnIndex* at rows that make *rowTester* return true,
+ // using the content of the cell at *majorColumnIndex*
+ // tags:
+ // public
+ // rowTester: function(Integer)|Integer
+ // If it's a function, it's a predicate to decide which rows are to be merged.
+ // It takes an integer (the row index), and should return true or false;
+ // startColumnIndex: Integer
+ // The column index of the left most cell that shall be merged.
+ // endColumnIndex: Integer
+ // The column index of the right most cell that shall be merged.
+ // majorColumnIndex: Integer?
+ // The column index of the cell whose content should be used as the content of the merged cell.
+ // It must be larger than or equal to the startColumnIndex, and less than or equal to the endColumnIndex.
+ // If it is omitted, the content of the leading edge (left-most for ltr, right most for rtl) cell will be used.
+ // return: Object | null
+ // A handler for the merged cells created by a call of this function.
+ // This handler can be used later to unmerge cells using the function unmergeCells
+ // If the merge is not valid, returns null;
+ var item = this._createRecord({
+ "row": rowTester,
+ "start": startColumnIndex,
+ "end": endColumnIndex,
+ "major": majorColumnIndex
+ });
+ if(item){
+ this._updateRows(item);
+ }
+ return item;
+ },
+ unmergeCells: function(mergeHandler){
+ // summary:
+ // Unmerge the cells that are merged by the *mergeHandler*, which represents a call to the function mergeCells.
+ // tags:
+ // public
+ // mergeHandler: object
+ // A handler for the merged cells created by a call of function mergeCells.
+ var idx;
+ if(mergeHandler && (idx = array.indexOf(this._records, mergeHandler)) >= 0){
+ this._records.splice(idx, 1);
+ this._updateRows(mergeHandler);
+ }
+ },
+ getMergedCells: function(){
+ // summary:
+ // Get all records of currently merged cells.
+ // tags:
+ // public
+ // return: Array
+ // An array of records for merged-cells.
+ // The record has the following structure:
+ // {
+ // "row": 1, //the row index
+ // "start": 2, //the start column index
+ // "end": 4, //the end column index
+ // "major": 3, //the major column index
+ // "handle": someHandle, //The handler that covers this merge cell record.
+ // }
+ var res = [];
+ for(var i in this._merged){
+ res = res.concat(this._merged[i]);
+ }
+ return res;
+ },
+ getMergedCellsByRow: function(rowIndex){
+ // summary:
+ // Get the records of currently merged cells at the given row.
+ // tags:
+ // public
+ // return: Array
+ // An array of records for merged-cells. See docs of getMergedCells.
+ return this._merged[rowIndex] || [];
+ },
+
+ //----------------Private--------------------------
+ _setupConfig: function(config){
+ array.forEach(config, this._createRecord, this);
+ },
+ _initEvents: function(){
+ array.forEach(this.grid.views.views, function(view){
+ this.connect(view, "onAfterRow", lang.hitch(this, "_onAfterRow", view.index));
+ }, this);
+ },
+ _mixinGrid: function(){
+ var g = this.grid;
+ g.mergeCells = lang.hitch(this, "mergeCells");
+ g.unmergeCells = lang.hitch(this, "unmergeCells");
+ g.getMergedCells = lang.hitch(this, "getMergedCells");
+ g.getMergedCellsByRow = lang.hitch(this, "getMergedCellsByRow");
+ },
+ _getWidth: function(colIndex){
+ var node = this.grid.layout.cells[colIndex].getHeaderNode();
+ return html.position(node).w;
+ },
+ _onAfterRow: function(viewIdx, rowIndex, subrows){
+ try{
+ if(rowIndex < 0){
+ return;
+ }
+ var result = [], i, j, len = this._records.length,
+ cells = this.grid.layout.cells;
+ //Apply merge-cell requests one by one.
+ for(i = 0; i < len; ++i){
+ var item = this._records[i];
+ var storeItem = this.grid._by_idx[rowIndex];
+ if(item.view == viewIdx && item.row(rowIndex, storeItem && storeItem.item, this.grid.store)){
+ var res = {
+ record: item,
+ hiddenCells: [],
+ totalWidth: 0,
+ majorNode: cells[item.major].getNode(rowIndex),
+ majorHeaderNode: cells[item.major].getHeaderNode()
+ };
+ //Calculated the width of merged cell.
+ for(j = item.start; j <= item.end; ++j){
+ var w = this._getWidth(j, rowIndex);
+ res.totalWidth += w;
+ if(j != item.major){
+ res.hiddenCells.push(cells[j].getNode(rowIndex));
+ }
+ }
+ //If width is valid, remember it. There may be multiple merges within one row.
+ if(subrows.length != 1 || res.totalWidth > 0){
+ //Remove conflicted merges.
+ for(j = result.length - 1; j >= 0; --j){
+ var r = result[j].record;
+ if((r.start >= item.start && r.start <= item.end) ||
+ (r.end >= item.start && r.end <= item.end)){
+ result.splice(j, 1);
+ }
+ }
+ result.push(res);
+ }
+ }
+ }
+ this._merged[rowIndex] = [];
+ array.forEach(result, function(res){
+ array.forEach(res.hiddenCells, function(node){
+ html.style(node, "display", "none");
+ });
+ var pbm = html.marginBox(res.majorHeaderNode).w - html.contentBox(res.majorHeaderNode).w;
+ var tw = res.totalWidth;
+
+ //Tricky for WebKit.
+ if(!html.isWebKit){
+ tw -= pbm;
+ }
+
+ html.style(res.majorNode, "width", tw + "px");
+ //In case we're dealing with multiple subrows.
+ res.majorNode.setAttribute("colspan", res.hiddenCells.length + 1);
+
+ this._merged[rowIndex].push({
+ "row": rowIndex,
+ "start": res.record.start,
+ "end": res.record.end,
+ "major": res.record.major,
+ "handle": res.record
+ });
+ }, this);
+ }catch(e){
+ console.warn("CellMerge._onAfterRow() error: ", rowIndex, e);
+ }
+ },
+ _createRecord: function(item){
+ if(this._isValid(item)){
+ item = {
+ "row": item.row,
+ "start": item.start,
+ "end": item.end,
+ "major": item.major
+ };
+ var cells = this.grid.layout.cells;
+ item.view = cells[item.start].view.index;
+ item.major = typeof item.major == "number" && !isNaN(item.major) ? item.major : item.start;
+ if(typeof item.row == "number"){
+ var r = item.row;
+ item.row = function(rowIndex){
+ return rowIndex === r;
+ };
+ }else if(typeof item.row == "string"){
+ var id = item.row;
+ item.row = function(rowIndex, storeItem, store){
+ try{
+ if(store && storeItem && store.getFeatures()['dojo.data.api.Identity']){
+ return store.getIdentity(storeItem) == id;
+ }
+ }catch(e){
+ console.error(e);
+ }
+ return false;
+ };
+ }
+ if(lang.isFunction(item.row)){
+ this._records.push(item);
+ return item;
+ }
+ }
+ return null;
+ },
+ _isValid: function(item){
+ var cells = this.grid.layout.cells,
+ colCount = cells.length;
+ return (lang.isObject(item) && ("row" in item) && ("start" in item) && ("end" in item) &&
+ item.start >= 0 && item.start < colCount &&
+ item.end > item.start && item.end < colCount &&
+ cells[item.start].view.index == cells[item.end].view.index &&
+ cells[item.start].subrow == cells[item.end].subrow &&
+ !(typeof item.major == "number" && (item.major < item.start || item.major > item.end)));
+ },
+ _updateRows: function(item){
+ var min = null;
+ for(var i = 0, count = this.grid.rowCount; i < count; ++i){
+ var storeItem = this.grid._by_idx[i];
+ if(storeItem && item.row(i, storeItem && storeItem.item, this.grid.store)){
+ this.grid.views.updateRow(i);
+ if(min === null){ min = i; }
+ }
+ }
+ if(min >= 0){
+ this.grid.scroller.rowHeightChanged(min);
+ }
+ }
+});
+
+EnhancedGrid.registerPlugin(CellMerge);
+
+return CellMerge;
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/Cookie.js b/js/dojo/dojox/grid/enhanced/plugins/Cookie.js
new file mode 100644
index 0000000..d0160f7
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/Cookie.js
@@ -0,0 +1,362 @@
+//>>built
+define("dojox/grid/enhanced/plugins/Cookie", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/lang",
+ "dojo/_base/sniff",
+ "dojo/_base/html",
+ "dojo/_base/json",
+ "dojo/_base/window",
+ "dojo/_base/unload",
+ "dojo/cookie",
+ "../_Plugin",
+ "../../_RowSelector",
+ "../../EnhancedGrid",
+ "../../cells/_base"
+], function(declare, array, lang, has, html, json, win, unload, cookie, _Plugin, _RowSelector, EnhancedGrid){
+
+ var gridCells = lang.getObject("dojox.grid.cells");
+
+ // Generate a cookie key for the given grid.
+ var _cookieKeyBuilder = function(grid){
+ return window.location + "/" + grid.id;
+ };
+
+ //Utilities:
+ var _getCellsFromStructure = function(structure){
+ var cells = [];
+ if(!lang.isArray(structure)){
+ structure = [structure];
+ }
+ array.forEach(structure,function(viewDef){
+ if(lang.isArray(viewDef)){
+ viewDef = {"cells" : viewDef};
+ }
+ var rows = viewDef.rows || viewDef.cells;
+ if(lang.isArray(rows)){
+ if(!lang.isArray(rows[0])){
+ rows = [rows];
+ }
+ array.forEach(rows, function(row){
+ if(lang.isArray(row)){
+ array.forEach(row, function(cell){
+ cells.push(cell);
+ });
+ }
+ });
+ }
+ });
+ return cells;
+ };
+
+ // Persist column width
+ var _loadColWidth = function(colWidths, grid){
+ if(lang.isArray(colWidths)){
+ var oldFunc = grid._setStructureAttr;
+ grid._setStructureAttr = function(structure){
+ if(!grid._colWidthLoaded){
+ grid._colWidthLoaded = true;
+ var cells = _getCellsFromStructure(structure);
+ for(var i = cells.length - 1; i >= 0; --i){
+ if(typeof colWidths[i] == "number"){
+ cells[i].width = colWidths[i] + "px";
+ }else if(colWidths[i] == 'hidden'){
+ cells[i].hidden = true;
+ }
+ }
+ }
+ oldFunc.call(grid, structure);
+ grid._setStructureAttr = oldFunc;
+ };
+ }
+ };
+
+
+ var _saveColWidth = function(grid){
+ return array.map(array.filter(grid.layout.cells, function(cell){
+ return !(cell.isRowSelector || cell instanceof gridCells.RowIndex);
+ }), function(cell){
+ return cell.hidden ? 'hidden' : html[has("webkit") ? "marginBox" : "contentBox"](cell.getHeaderNode()).w;
+ });
+ };
+
+ // Persist column order
+ var _loadColumnOrder = function(colOrder, grid){
+ if(colOrder && array.every(colOrder, function(viewInfo){
+ return lang.isArray(viewInfo) && array.every(viewInfo, function(subrowInfo){
+ return lang.isArray(subrowInfo) && subrowInfo.length > 0;
+ });
+ })){
+ var oldFunc = grid._setStructureAttr;
+ var isCell = function(def){
+ return ("name" in def || "field" in def || "get" in def);
+ };
+ var isView = function(def){
+ return (def !== null && lang.isObject(def) &&
+ ("cells" in def || "rows" in def || ("type" in def && !isCell(def))));
+ };
+ grid._setStructureAttr = function(structure){
+ if(!grid._colOrderLoaded){
+ grid._colOrderLoaded = true;
+ grid._setStructureAttr = oldFunc;
+ structure = lang.clone(structure);
+ if(lang.isArray(structure) && !array.some(structure, isView)){
+ structure = [{ cells: structure }];
+ }else if(isView(structure)){
+ structure = [structure];
+ }
+ var cells = _getCellsFromStructure(structure);
+ array.forEach(lang.isArray(structure) ? structure : [structure], function(viewDef, viewIdx){
+ var cellArray = viewDef;
+ if(lang.isArray(viewDef)){
+ viewDef.splice(0, viewDef.length);
+ }else{
+ delete viewDef.rows;
+ cellArray = viewDef.cells = [];
+ }
+ array.forEach(colOrder[viewIdx], function(subrow){
+ array.forEach(subrow, function(cellInfo){
+ var i, cell;
+ for(i = 0; i < cells.length; ++i){
+ cell = cells[i];
+ if(json.toJson({'name':cell.name,'field':cell.field}) == json.toJson(cellInfo)){
+ break;
+ }
+ }
+ if(i < cells.length){
+ cellArray.push(cell);
+ }
+ });
+ });
+ });
+ }
+ oldFunc.call(grid, structure);
+ };
+ }
+ };
+
+ var _saveColumnOrder = function(grid){
+ var colOrder = array.map(array.filter(grid.views.views, function(view){
+ return !(view instanceof _RowSelector);
+ }), function(view){
+ return array.map(view.structure.cells, function(subrow){
+ return array.map(array.filter(subrow, function(cell){
+ return !(cell.isRowSelector || cell instanceof gridCells.RowIndex);
+ }), function(cell){
+ return {
+ "name": cell.name,
+ "field": cell.field
+ };
+ });
+ });
+ });
+ return colOrder;
+ };
+
+ // Persist sorting order
+ var _loadSortOrder = function(sortOrder, grid){
+ try{
+ if(lang.isObject(sortOrder)){
+ grid.setSortIndex(sortOrder.idx, sortOrder.asc);
+ }
+ }catch(e){
+ //setSortIndex will finally call _fetch, some exceptions will be throw
+ //'cause the grid hasn't be fully loaded now. Just ignore them.
+ }
+ };
+
+ var _saveSortOrder = function(grid){
+ return {
+ idx: grid.getSortIndex(),
+ asc: grid.getSortAsc()
+ };
+ };
+
+ if(!has("ie")){
+ // Now in non-IE, widgets are no longer destroyed on page unload,
+ // so we have to destroy it manually to trigger saving cookie.
+ unload.addOnWindowUnload(function(){
+ array.forEach(dijit.findWidgets(win.body()), function(widget){
+ if(widget instanceof EnhancedGrid && !widget._destroyed){
+ widget.destroyRecursive();
+ }
+ });
+ });
+ }
+
+ var Cookie = declare("dojox.grid.enhanced.plugins.Cookie", _Plugin, {
+ // summary:
+ // This plugin provides a way to persist some grid features in cookie.
+ // Default persistable features are:
+ // column width: "columnWidth" (handler name)
+ // column order: "columnOrder"
+ // sorting order: "sortOrder"
+ //
+ // Grid users can define new persistable features
+ // by calling the following before grid is initialized (that is, during "preInit");
+ // | grid.addCookieHandler({
+ // | name: "a name for the new persistable feature",
+ // | onLoad: function(savedObject, grid){
+ // | //load the cookie.
+ // | },
+ // | onSave: function(grid){
+ // | //save the cookie.
+ // | }
+ // | });
+
+ // name: String
+ // Plugin name
+ name: "cookie",
+
+ _cookieEnabled: true,
+
+ constructor: function(grid, args){
+ this.grid = grid;
+ args = (args && lang.isObject(args)) ? args : {};
+ this.cookieProps = args.cookieProps;
+ this._cookieHandlers = [];
+ this._mixinGrid();
+
+ //Column width & simple sorting & column reorder are base grid features, so they must be supported.
+ this.addCookieHandler({
+ name: "columnWidth",
+ onLoad: _loadColWidth,
+ onSave: _saveColWidth
+ });
+ this.addCookieHandler({
+ name: "columnOrder",
+ onLoad: _loadColumnOrder,
+ onSave: _saveColumnOrder
+ });
+ this.addCookieHandler({
+ name: "sortOrder",
+ onLoad: _loadSortOrder,
+ onSave: _saveSortOrder
+ });
+
+ array.forEach(this._cookieHandlers, function(handler){
+ if(args[handler.name] === false){
+ handler.enable = false;
+ }
+ }, this);
+ },
+ destroy:function(){
+ this._saveCookie();
+ this._cookieHandlers = null;
+ this.inherited(arguments);
+ },
+ _mixinGrid: function(){
+ var g = this.grid;
+ g.addCookieHandler = lang.hitch(this, "addCookieHandler");
+ g.removeCookie = lang.hitch(this, "removeCookie");
+ g.setCookieEnabled = lang.hitch(this, "setCookieEnabled");
+ g.getCookieEnabled = lang.hitch(this, "getCookieEnabled");
+ },
+ _saveCookie: function(){
+ if(this.getCookieEnabled()){
+ var ck = {},
+ chs = this._cookieHandlers,
+ cookieProps = this.cookieProps,
+ cookieKey = _cookieKeyBuilder(this.grid);
+ for(var i = chs.length-1; i >= 0; --i){
+ if(chs[i].enabled){
+ //Do the real saving work here.
+ ck[chs[i].name] = chs[i].onSave(this.grid);
+ }
+ }
+ cookieProps = lang.isObject(this.cookieProps) ? this.cookieProps : {};
+ cookie(cookieKey, json.toJson(ck), cookieProps);
+ }else{
+ this.removeCookie();
+ }
+ },
+ onPreInit: function(){
+ var grid = this.grid,
+ chs = this._cookieHandlers,
+ cookieKey = _cookieKeyBuilder(grid),
+ ck = cookie(cookieKey);
+ if(ck){
+ ck = json.fromJson(ck);
+ for(var i = 0; i < chs.length; ++i){
+ if(chs[i].name in ck && chs[i].enabled){
+ //Do the real loading work here.
+ chs[i].onLoad(ck[chs[i].name], grid);
+ }
+ }
+ }
+ this._cookie = ck || {};
+ this._cookieStartedup = true;
+ },
+ addCookieHandler: function(args){
+ // summary:
+ // If a grid plugin wants cookie service, call this.
+ // This must be called during preInit.
+ // args: Object
+ // An object with the following structure:
+ // | {
+ // | name: "some-string",
+ // | onLoad: /* void */ function(/* object */partOfCookie, /* EDG */grid){...},
+ // | onSave: /* object */ function(/* EDG */grid){...}
+ // | }
+ if(args.name){
+ var dummy = function(){};
+ args.onLoad = args.onLoad || dummy;
+ args.onSave = args.onSave || dummy;
+ if(!("enabled" in args)){
+ args.enabled = true;
+ }
+ for(var i = this._cookieHandlers.length - 1; i >= 0; --i){
+ if(this._cookieHandlers[i].name == args.name){
+ this._cookieHandlers.splice(i, 1);
+ }
+ }
+ this._cookieHandlers.push(args);
+ if(this._cookieStartedup && args.name in this._cookie){
+ args.onLoad(this._cookie[args.name], this.grid);
+ }
+ }
+ },
+ removeCookie: function(){
+ // summary:
+ // Remove cookie for this grid.
+ var key = _cookieKeyBuilder(this.grid);
+ cookie(key, null, {expires: -1});
+ },
+ setCookieEnabled: function(cookieName, enabled){
+ // summary:
+ // A setter to enable|disable cookie support for a particular Grid feature.
+ // cookieName: String?
+ // Name of a cookie handler if provided, otherwise for all cookies.
+ // enabled: Boolean
+ if(typeof cookieName == 'string'){
+ var chs = this._cookieHandlers;
+ for(var i = chs.length - 1; i >= 0; --i){
+ if(chs[i].name === cookieName){
+ chs[i].enabled = !!enabled;
+ }
+ }
+ }else{
+ this._cookieEnabled = !!cookieName;
+ if(!this._cookieEnabled){ this.removeCookie(); }
+ }
+ },
+ getCookieEnabled: function(cookieName){
+ // summary:
+ // A getter to check cookie support of a particular Grid feature.
+ // cookieName: String?
+ // Name of a cookie handler if provided, otherwise for all cookies.
+ if(lang.isString(cookieName)){
+ var chs = this._cookieHandlers;
+ for(var i = chs.length - 1; i >= 0; --i){
+ if(chs[i].name == cookieName){ return chs[i].enabled; }
+ }
+ return false;
+ }
+ return this._cookieEnabled;
+ }
+ });
+
+ EnhancedGrid.registerPlugin(Cookie, {"preInit": true});
+
+ return Cookie;
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/Dialog.js b/js/dojo/dojox/grid/enhanced/plugins/Dialog.js
new file mode 100644
index 0000000..97dbbd4
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/Dialog.js
@@ -0,0 +1,40 @@
+//>>built
+define("dojox/grid/enhanced/plugins/Dialog", [
+ "dojo/_base/declare",
+ "dojo/_base/html",
+ "dojo/window",
+ "dijit/Dialog"
+], function(declare, html, win, Dialog){
+
+return declare("dojox.grid.enhanced.plugins.Dialog", Dialog, {
+ refNode: null,
+ _position: function(){
+ if(this.refNode && !this._relativePosition){
+ var refPos = html.position(html.byId(this.refNode)),
+ thisPos = html.position(this.domNode),
+ viewPort = win.getBox();
+ if(thisPos.w && thisPos.h){
+ if(refPos.x < 0){
+ refPos.x = 0;
+ }
+ if(refPos.x + refPos.w > viewPort.w){
+ refPos.w = viewPort.w - refPos.x;
+ }
+ if(refPos.y < 0){
+ refPos.y = 0;
+ }
+ if(refPos.y + refPos.h > viewPort.h){
+ refPos.h = viewPort.h - refPos.y;
+ }
+ refPos.x = refPos.x + refPos.w / 2 - thisPos.w / 2;
+ refPos.y = refPos.y + refPos.h / 2 - thisPos.h / 2;
+ if(refPos.x >= 0 && refPos.x + thisPos.w <= viewPort.w &&
+ refPos.y >= 0 && refPos.y + thisPos.h <= viewPort.h){
+ this._relativePosition = refPos;
+ }
+ }
+ }
+ this.inherited(arguments);
+ }
+});
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/DnD.js b/js/dojo/dojox/grid/enhanced/plugins/DnD.js
new file mode 100644
index 0000000..e9306ed
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/DnD.js
@@ -0,0 +1,1094 @@
+//>>built
+define("dojox/grid/enhanced/plugins/DnD", [
+ "dojo/_base/kernel",
+ "dojo/_base/declare",
+ "dojo/_base/connect",
+ "dojo/_base/array",
+ "dojo/_base/lang",
+ "dojo/_base/html",
+ "dojo/_base/json",
+ "dojo/_base/window",
+ "dojo/query",
+ "dojo/keys",
+ "dojo/dnd/Source",
+ "dojo/dnd/Avatar",
+ "../_Plugin",
+ "../../EnhancedGrid",
+ "./Selector",
+ "./Rearrange",
+ "dojo/dnd/Manager"
+], function(dojo, declare, connect, array, lang, html, json, win, query, keys, Source, Avatar, _Plugin, EnhancedGrid){
+
+var _devideToArrays = function(a){
+ a.sort(function(v1, v2){
+ return v1 - v2;
+ });
+ var arr = [[a[0]]];
+ for(var i = 1, j = 0; i < a.length; ++i){
+ if(a[i] == a[i-1] + 1){
+ arr[j].push(a[i]);
+ }else{
+ arr[++j] = [a[i]];
+ }
+ }
+ return arr;
+ },
+ _joinToArray = function(arrays){
+ var a = arrays[0];
+ for(var i = 1; i < arrays.length; ++i){
+ a = a.concat(arrays[i]);
+ }
+ return a;
+ };
+var GridDnDElement = declare("dojox.grid.enhanced.plugins.GridDnDElement", null, {
+ constructor: function(dndPlugin){
+ this.plugin = dndPlugin;
+ this.node = html.create("div");
+ this._items = {};
+ },
+ destroy: function(){
+ this.plugin = null;
+ html.destroy(this.node);
+ this.node = null;
+ this._items = null;
+ },
+ createDnDNodes: function(dndRegion){
+ this.destroyDnDNodes();
+ var acceptType = ["grid/" + dndRegion.type + "s"];
+ var itemNodeIdBase = this.plugin.grid.id + "_dndItem";
+ array.forEach(dndRegion.selected, function(range, i){
+ var id = itemNodeIdBase + i;
+ this._items[id] = {
+ "type": acceptType,
+ "data": range,
+ "dndPlugin": this.plugin
+ };
+ this.node.appendChild(html.create("div", {
+ "id": id
+ }));
+ }, this);
+ },
+ getDnDNodes: function(){
+ return array.map(this.node.childNodes, function(node){
+ return node;
+ });
+ },
+ destroyDnDNodes: function(){
+ html.empty(this.node);
+ this._items = {};
+ },
+ getItem: function(nodeId){
+ return this._items[nodeId];
+ }
+});
+var GridDnDSource = declare("dojox.grid.enhanced.plugins.GridDnDSource", Source,{
+ accept: ["grid/cells", "grid/rows", "grid/cols"],
+ constructor: function(node, param){
+ this.grid = param.grid;
+ this.dndElem = param.dndElem;
+ this.dndPlugin = param.dnd;
+ this.sourcePlugin = null;
+ },
+ destroy: function(){
+ this.inherited(arguments);
+ this.grid = null;
+ this.dndElem = null;
+ this.dndPlugin = null;
+ this.sourcePlugin = null;
+ },
+ getItem: function(nodeId){
+ return this.dndElem.getItem(nodeId);
+ },
+ checkAcceptance: function(source, nodes){
+ if(this != source && nodes[0]){
+ var item = source.getItem(nodes[0].id);
+ if(item.dndPlugin){
+ var type = item.type;
+ for(var j = 0; j < type.length; ++j){
+ if(type[j] in this.accept){
+ if(this.dndPlugin._canAccept(item.dndPlugin)){
+ this.sourcePlugin = item.dndPlugin;
+ }else{
+ return false;
+ }
+ break;
+ }
+ }
+ }else if("grid/rows" in this.accept){
+ var rows = [];
+ array.forEach(nodes, function(node){
+ var item = source.getItem(node.id);
+ if(item.data && array.indexOf(item.type, "grid/rows") >= 0){
+ var rowData = item.data;
+ if(typeof item.data == "string"){
+ rowData = json.fromJson(item.data);
+ }
+ if(rowData){
+ rows.push(rowData);
+ }
+ }
+ });
+ if(rows.length){
+ this.sourcePlugin = {
+ _dndRegion: {
+ type: "row",
+ selected: [rows]
+ }
+ };
+ }else{
+ return false;
+ }
+ }
+ }
+ return this.inherited(arguments);
+ },
+ onDraggingOver: function(){
+ this.dndPlugin.onDraggingOver(this.sourcePlugin);
+ },
+ onDraggingOut: function(){
+ this.dndPlugin.onDraggingOut(this.sourcePlugin);
+ },
+ onDndDrop: function(source, nodes, copy, target){
+ //this.inherited(arguments);
+ this.onDndCancel();
+ if(this != source && this == target){
+ this.dndPlugin.onDragIn(this.sourcePlugin, copy);
+ }
+ }
+});
+
+var GridDnDAvatar = declare("dojox.grid.enhanced.plugins.GridDnDAvatar", Avatar, {
+ construct: function(){
+ // summary:
+ // constructor function;
+ // it is separate so it can be (dynamically) overwritten in case of need
+ this._itemType = this.manager._dndPlugin._dndRegion.type;
+ this._itemCount = this._getItemCount();
+
+ this.isA11y = html.hasClass(win.body(), "dijit_a11y");
+ var a = html.create("table", {
+ "border": "0",
+ "cellspacing": "0",
+ "class": "dojoxGridDndAvatar",
+ "style": {
+ position: "absolute",
+ zIndex: "1999",
+ margin: "0px"
+ }
+ }),
+ source = this.manager.source,
+ b = html.create("tbody", null, a),
+ tr = html.create("tr", null, b),
+ td = html.create("td", {
+ "class": "dojoxGridDnDIcon"
+ }, tr);
+ if(this.isA11y){
+ html.create("span", {
+ "id" : "a11yIcon",
+ "innerHTML" : this.manager.copy ? '+' : "<"
+ }, td);
+ }
+ td = html.create("td", {
+ "class" : "dojoxGridDnDItemIcon " + this._getGridDnDIconClass()
+ }, tr);
+ td = html.create("td", null, tr);
+ html.create("span", {
+ "class": "dojoxGridDnDItemCount",
+ "innerHTML": source.generateText ? this._generateText() : ""
+ }, td);
+ // we have to set the opacity on IE only after the node is live
+ html.style(tr, {
+ "opacity": 0.9
+ });
+ this.node = a;
+ },
+ _getItemCount: function(){
+ var selected = this.manager._dndPlugin._dndRegion.selected,
+ count = 0;
+ switch(this._itemType){
+ case "cell":
+ selected = selected[0];
+ var cells = this.manager._dndPlugin.grid.layout.cells,
+ colCount = selected.max.col - selected.min.col + 1,
+ rowCount = selected.max.row - selected.min.row + 1;
+ if(colCount > 1){
+ for(var i = selected.min.col; i <= selected.max.col; ++i){
+ if(cells[i].hidden){
+ --colCount;
+ }
+ }
+ }
+ count = colCount * rowCount;
+ break;
+ case "row":
+ case "col":
+ count = _joinToArray(selected).length;
+ }
+ return count;
+ },
+ _getGridDnDIconClass: function(){
+ return {
+ "row": ["dojoxGridDnDIconRowSingle", "dojoxGridDnDIconRowMulti"],
+ "col": ["dojoxGridDnDIconColSingle", "dojoxGridDnDIconColMulti"],
+ "cell": ["dojoxGridDnDIconCellSingle", "dojoxGridDnDIconCellMulti"]
+ }[this._itemType][this._itemCount == 1 ? 0 : 1];
+ },
+ _generateText: function(){
+ // summary:
+ // generates a proper text to reflect copying or moving of items
+ return "(" + this._itemCount + ")";
+ }
+});
+var DnD = declare("dojox.grid.enhanced.plugins.DnD", _Plugin, {
+ // summary:
+ // Provide drag and drop for grid columns/rows/cells within grid and out of grid.
+ // The store of grid must implement dojo.data.api.Write.
+ // DnD selected columns:
+ // Support moving within grid, moving/copying out of grid to a non-grid DnD target.
+ // DnD selected rows:
+ // Support moving within grid, moving/copying out of grid to any DnD target.
+ // DnD selected cells (in rectangle shape only):
+ // Support moving/copying within grid, moving/copying out of grid to any DnD target.
+ //
+
+ // name: String,
+ // plugin name;
+ name: "dnd",
+
+ _targetAnchorBorderWidth: 2,
+ _copyOnly: false,
+ _config: {
+ "row":{
+ "within":true,
+ "in":true,
+ "out":true
+ },
+ "col":{
+ "within":true,
+ "in":true,
+ "out":true
+ },
+ "cell":{
+ "within":true,
+ "in":true,
+ "out":true
+ }
+ },
+ constructor: function(grid, args){
+ this.grid = grid;
+ this._config = lang.clone(this._config);
+ args = lang.isObject(args) ? args : {};
+ this.setupConfig(args.dndConfig);
+ this._copyOnly = !!args.copyOnly;
+
+ //Get the plugins we are dependent on.
+ this._mixinGrid();
+ this.selector = grid.pluginMgr.getPlugin("selector");
+ this.rearranger = grid.pluginMgr.getPlugin("rearrange");
+ //TODO: waiting for a better plugin framework to pass args to dependent plugins.
+ this.rearranger.setArgs(args);
+
+ //Initialized the components we need.
+ this._clear();
+ this._elem = new GridDnDElement(this);
+ this._source = new GridDnDSource(this._elem.node, {
+ "grid": grid,
+ "dndElem": this._elem,
+ "dnd": this
+ });
+ this._container = query(".dojoxGridMasterView", this.grid.domNode)[0];
+ this._initEvents();
+ },
+ destroy: function(){
+ this.inherited(arguments);
+ this._clear();
+ this._source.destroy();
+ this._elem.destroy();
+ this._container = null;
+ this.grid = null;
+ this.selector = null;
+ this.rearranger = null;
+ this._config = null;
+ },
+ _mixinGrid: function(){
+ // summary:
+ // Provide APIs for grid.
+ this.grid.setupDnDConfig = lang.hitch(this, "setupConfig");
+ this.grid.dndCopyOnly = lang.hitch(this, "copyOnly");
+ },
+ setupConfig: function(config){
+ // summary:
+ // Configure which DnD functionalities are needed.
+ // Combination of any item from type set ("row", "col", "cell")
+ // and any item from mode set("within", "in", "out") is configurable.
+ //
+ // "row", "col", "cell" are straitforward, while the other 3 are explained below:
+ // "within": DnD within grid, that is, column/row reordering and cell moving/copying.
+ // "in": Whether allowed to accept rows/cells (currently not support columns) from another grid.
+ // "out": Whether allowed to drag out of grid, to another grid or even to any other DnD target.
+ //
+ // If not provided in the config, will use the default.
+ // When declared together, Mode set has higher priority than type set.
+ // config: Object
+ // DnD configuration object.
+ // See the examples below.
+ // example:
+ // The following code disables row DnD within grid,
+ // but still can drag rows out of grid or drag rows from other gird.
+ // | setUpConfig({
+ // | "row": {
+ // | "within": false
+ // | }
+ // | });
+ //
+ // The opposite way is also okay:
+ // | setUpConfig({
+ // | "within": {
+ // | "row": false
+ // | }
+ // | });
+ //
+ // And if you'd like to disable/enable a whole set, here's a shortcut:
+ // | setUpConfig({
+ // | "cell", true,
+ // | "out": false
+ // | });
+ //
+ // Because mode has higher priority than type, the following will disable row dnd within grid:
+ // | setUpConfig({
+ // | "within", {
+ // | "row": false;
+ // | },
+ // | "row", {
+ // | "within": true
+ // | }
+ // | });
+ if(config && lang.isObject(config)){
+ var firstLevel = ["row", "col", "cell"],
+ secondLevel = ["within", "in", "out"],
+ cfg = this._config;
+ array.forEach(firstLevel, function(type){
+ if(type in config){
+ var t = config[type];
+ if(t && lang.isObject(t)){
+ array.forEach(secondLevel, function(mode){
+ if(mode in t){
+ cfg[type][mode] = !!t[mode];
+ }
+ });
+ }else{
+ array.forEach(secondLevel, function(mode){
+ cfg[type][mode] = !!t;
+ });
+ }
+ }
+ });
+ array.forEach(secondLevel, function(mode){
+ if(mode in config){
+ var m = config[mode];
+ if(m && lang.isObject(m)){
+ array.forEach(firstLevel, function(type){
+ if(type in m){
+ cfg[type][mode] = !!m[type];
+ }
+ });
+ }else{
+ array.forEach(firstLevel, function(type){
+ cfg[type][mode] = !!m;
+ });
+ }
+ }
+ });
+ }
+ },
+ copyOnly: function(isCopyOnly){
+ // summary:
+ // Setter/getter of this._copyOnly.
+ if(typeof isCopyOnly != "undefined"){
+ this._copyOnly = !!isCopyOnly;
+ }
+ return this._copyOnly;
+ },
+ _isOutOfGrid: function(evt){
+ var gridPos = html.position(this.grid.domNode), x = evt.clientX, y = evt.clientY;
+ return y < gridPos.y || y > gridPos.y + gridPos.h ||
+ x < gridPos.x || x > gridPos.x + gridPos.w;
+ },
+ _onMouseMove: function(evt){
+ if(this._dndRegion && !this._dnding && !this._externalDnd){
+ this._dnding = true;
+ this._startDnd(evt);
+ }else{
+ if(this._isMouseDown && !this._dndRegion){
+ delete this._isMouseDown;
+ this._oldCursor = html.style(win.body(), "cursor");
+ html.style(win.body(), "cursor", "not-allowed");
+ }
+ //TODO: should implement as mouseenter/mouseleave
+ //But we have an avatar under mouse when dnd, and this will cause a lot of mouseenter in FF.
+ var isOut = this._isOutOfGrid(evt);
+ if(!this._alreadyOut && isOut){
+ this._alreadyOut = true;
+ if(this._dnding){
+ this._destroyDnDUI(true, false);
+ }
+ this._moveEvent = evt;
+ this._source.onOutEvent();
+ }else if(this._alreadyOut && !isOut){
+ this._alreadyOut = false;
+ if(this._dnding){
+ this._createDnDUI(evt, true);
+ }
+ this._moveEvent = evt;
+ this._source.onOverEvent();
+ }
+ }
+ },
+ _onMouseUp: function(){
+ if(!this._extDnding && !this._isSource){
+ var isInner = this._dnding && !this._alreadyOut;
+ if(isInner && this._config[this._dndRegion.type]["within"]){
+ this._rearrange();
+ }
+ this._endDnd(isInner);
+ }
+ html.style(win.body(), "cursor", this._oldCursor || "");
+ delete this._isMouseDown;
+ },
+ _initEvents: function(){
+ var g = this.grid, s = this.selector;
+ this.connect(win.doc, "onmousemove", "_onMouseMove");
+ this.connect(win.doc, "onmouseup", "_onMouseUp");
+
+ this.connect(g, "onCellMouseOver", function(evt){
+ if(!this._dnding && !s.isSelecting() && !evt.ctrlKey){
+ this._dndReady = s.isSelected("cell", evt.rowIndex, evt.cell.index);
+ s.selectEnabled(!this._dndReady);
+ }
+ });
+ this.connect(g, "onHeaderCellMouseOver", function(evt){
+ if(this._dndReady){
+ s.selectEnabled(true);
+ }
+ });
+ this.connect(g, "onRowMouseOver", function(evt){
+ if(this._dndReady && !evt.cell){
+ s.selectEnabled(true);
+ }
+ });
+ this.connect(g, "onCellMouseDown", function(evt){
+ if(!evt.ctrlKey && this._dndReady){
+ this._dndRegion = this._getDnDRegion(evt.rowIndex, evt.cell.index);
+ this._isMouseDown = true;
+ }
+ });
+ this.connect(g, "onCellMouseUp", function(evt){
+ if(!this._dndReady && !s.isSelecting() && evt.cell){
+ this._dndReady = s.isSelected("cell", evt.rowIndex, evt.cell.index);
+ s.selectEnabled(!this._dndReady);
+ }
+ });
+ this.connect(g, "onCellClick", function(evt){
+ if(this._dndReady && !evt.ctrlKey && !evt.shiftKey){
+ s.select("cell", evt.rowIndex, evt.cell.index);
+ }
+ });
+ this.connect(g, "onEndAutoScroll", function(isVertical, isForward, view, target, evt){
+ if(this._dnding){
+ this._markTargetAnchor(evt);
+ }
+ });
+ this.connect(win.doc, "onkeydown", function(evt){
+ if(evt.keyCode == keys.ESCAPE){
+ this._endDnd(false);
+ }else if(evt.keyCode == keys.CTRL){
+ s.selectEnabled(true);
+ this._isCopy = true;
+ }
+ });
+ this.connect(win.doc, "onkeyup", function(evt){
+ if(evt.keyCode == keys.CTRL){
+ s.selectEnabled(!this._dndReady);
+ this._isCopy = false;
+ }
+ });
+ },
+ _clear: function(){
+ this._dndRegion = null;
+ this._target = null;
+ this._moveEvent = null;
+ this._targetAnchor = {};
+ this._dnding = false;
+ this._externalDnd = false;
+ this._isSource = false;
+ this._alreadyOut = false;
+ this._extDnding = false;
+ },
+ _getDnDRegion: function(rowIndex, colIndex){
+ var s = this.selector,
+ selected = s._selected,
+ flag = (!!selected.cell.length) | (!!selected.row.length << 1) | (!!selected.col.length << 2),
+ type;
+ switch(flag){
+ case 1:
+ type = "cell";
+ if(!this._config[type]["within"] && !this._config[type]["out"]){
+ return null;
+ }
+ var cells = this.grid.layout.cells,
+ getCount = function(range){
+ var hiddenColCnt = 0;
+ for(var i = range.min.col; i <= range.max.col; ++i){
+ if(cells[i].hidden){
+ ++hiddenColCnt;
+ }
+ }
+ return (range.max.row - range.min.row + 1) * (range.max.col - range.min.col + 1 - hiddenColCnt);
+ },
+ inRange = function(item, range){
+ return item.row >= range.min.row && item.row <= range.max.row &&
+ item.col >= range.min.col && item.col <= range.max.col;
+ },
+ range = {
+ max: {
+ row: -1,
+ col: -1
+ },
+ min: {
+ row: Infinity,
+ col: Infinity
+ }
+ };
+
+ array.forEach(selected[type], function(item){
+ if(item.row < range.min.row){
+ range.min.row = item.row;
+ }
+ if(item.row > range.max.row){
+ range.max.row = item.row;
+ }
+ if(item.col < range.min.col){
+ range.min.col = item.col;
+ }
+ if(item.col > range.max.col){
+ range.max.col = item.col;
+ }
+ });
+ if(array.some(selected[type], function(item){
+ return item.row == rowIndex && item.col == colIndex;
+ })){
+ if(getCount(range) == selected[type].length && array.every(selected[type], function(item){
+ return inRange(item, range);
+ })){
+ return {
+ "type": type,
+ "selected": [range],
+ "handle": {
+ "row": rowIndex,
+ "col": colIndex
+ }
+ };
+ }
+ }
+ return null;
+ case 2: case 4:
+ type = flag == 2 ? "row" : "col";
+ if(!this._config[type]["within"] && !this._config[type]["out"]){
+ return null;
+ }
+ var res = s.getSelected(type);
+ if(res.length){
+ return {
+ "type": type,
+ "selected": _devideToArrays(res),
+ "handle": flag == 2 ? rowIndex : colIndex
+ };
+ }
+ return null;
+ }
+ return null;
+ },
+ _startDnd: function(evt){
+ this._createDnDUI(evt);
+ },
+ _endDnd: function(destroySource){
+ this._destroyDnDUI(false, destroySource);
+ this._clear();
+ },
+ _createDnDUI: function(evt, isMovingIn){
+ //By default the master view of grid do not have height, because the children in it are all positioned absolutely.
+ //But we need it to contain avatars.
+ var viewPos = html.position(this.grid.views.views[0].domNode);
+ html.style(this._container, "height", viewPos.h + "px");
+ try{
+ //If moving in from out side, dnd source is already created.
+ if(!isMovingIn){
+ this._createSource(evt);
+ }
+ this._createMoveable(evt);
+ this._oldCursor = html.style(win.body(), "cursor");
+ html.style(win.body(), "cursor", "default");
+ }catch(e){
+ console.warn("DnD._createDnDUI() error:", e);
+ }
+ },
+ _destroyDnDUI: function(isMovingOut, destroySource){
+ try{
+ if(destroySource){
+ this._destroySource();
+ }
+ this._unmarkTargetAnchor();
+ if(!isMovingOut){
+ this._destroyMoveable();
+ }
+ html.style(win.body(), "cursor", this._oldCursor);
+ }catch(e){
+ console.warn("DnD._destroyDnDUI() error:", this.grid.id, e);
+ }
+ },
+ _createSource: function(evt){
+ this._elem.createDnDNodes(this._dndRegion);
+ var m = dojo.dnd.manager();
+ var oldMakeAvatar = m.makeAvatar;
+ m._dndPlugin = this;
+ m.makeAvatar = function(){
+ var avatar = new GridDnDAvatar(m);
+ delete m._dndPlugin;
+ return avatar;
+ };
+ m.startDrag(this._source, this._elem.getDnDNodes(), evt.ctrlKey);
+ m.makeAvatar = oldMakeAvatar;
+ m.onMouseMove(evt);
+ },
+ _destroySource: function(){
+ connect.publish("/dnd/cancel");
+ },
+ _createMoveable: function(evt){
+ if(!this._markTagetAnchorHandler){
+ this._markTagetAnchorHandler = this.connect(win.doc, "onmousemove", "_markTargetAnchor");
+ }
+ },
+ _destroyMoveable: function(){
+ this.disconnect(this._markTagetAnchorHandler);
+ delete this._markTagetAnchorHandler;
+ },
+ _calcColTargetAnchorPos: function(evt, containerPos){
+ // summary:
+ // Calculate the position of the column DnD avatar
+ var i, headPos, left, target, ex = evt.clientX,
+ cells = this.grid.layout.cells,
+ ltr = html._isBodyLtr(),
+ headers = this._getVisibleHeaders();
+ for(i = 0; i < headers.length; ++i){
+ headPos = html.position(headers[i].node);
+ if(ltr ? ((i === 0 || ex >= headPos.x) && ex < headPos.x + headPos.w) :
+ ((i === 0 || ex < headPos.x + headPos.w) && ex >= headPos.x)){
+ left = headPos.x + (ltr ? 0 : headPos.w);
+ break;
+ }else if(ltr ? (i === headers.length - 1 && ex >= headPos.x + headPos.w) :
+ (i === headers.length - 1 && ex < headPos.x)){
+ ++i;
+ left = headPos.x + (ltr ? headPos.w : 0);
+ break;
+ }
+ }
+ if(i < headers.length){
+ target = headers[i].cell.index;
+ if(this.selector.isSelected("col", target) && this.selector.isSelected("col", target - 1)){
+ var ranges = this._dndRegion.selected;
+ for(i = 0; i < ranges.length; ++i){
+ if(array.indexOf(ranges[i], target) >= 0){
+ target = ranges[i][0];
+ headPos = html.position(cells[target].getHeaderNode());
+ left = headPos.x + (ltr ? 0 : headPos.w);
+ break;
+ }
+ }
+ }
+ }else{
+ target = cells.length;
+ }
+ this._target = target;
+ return left - containerPos.x;
+ },
+ _calcRowTargetAnchorPos: function(evt, containerPos){
+ // summary:
+ // Calculate the position of the row DnD avatar
+ var g = this.grid, top, i = 0,
+ cells = g.layout.cells;
+ while(cells[i].hidden){ ++i; }
+ var cell = g.layout.cells[i],
+ rowIndex = g.scroller.firstVisibleRow,
+ cellNode = cell.getNode(rowIndex);
+ if(!cellNode){
+ //if the target grid is empty, set to -1
+ //which will be processed in Rearrange
+ this._target = -1;
+ return 0; //position of the insert bar
+ }
+ var nodePos = html.position(cellNode);
+ while(nodePos.y + nodePos.h < evt.clientY){
+ if(++rowIndex >= g.rowCount){
+ break;
+ }
+ nodePos = html.position(cell.getNode(rowIndex));
+ }
+ if(rowIndex < g.rowCount){
+ if(this.selector.isSelected("row", rowIndex) && this.selector.isSelected("row", rowIndex - 1)){
+ var ranges = this._dndRegion.selected;
+ for(i = 0; i < ranges.length; ++i){
+ if(array.indexOf(ranges[i], rowIndex) >= 0){
+ rowIndex = ranges[i][0];
+ nodePos = html.position(cell.getNode(rowIndex));
+ break;
+ }
+ }
+ }
+ top = nodePos.y;
+ }else{
+ top = nodePos.y + nodePos.h;
+ }
+ this._target = rowIndex;
+ return top - containerPos.y;
+ },
+ _calcCellTargetAnchorPos: function(evt, containerPos, targetAnchor){
+ // summary:
+ // Calculate the position of the cell DnD avatar
+ var s = this._dndRegion.selected[0],
+ origin = this._dndRegion.handle,
+ g = this.grid, ltr = html._isBodyLtr(),
+ cells = g.layout.cells, headPos,
+ minPos, maxPos, headers,
+ height, width, left, top,
+ minCol, maxCol, i,
+ preSpan = origin.col - s.min.col,
+ postSpan = s.max.col - origin.col,
+ leftTopDiv, rightBottomDiv;
+ if(!targetAnchor.childNodes.length){
+ leftTopDiv = html.create("div", {
+ "class": "dojoxGridCellBorderLeftTopDIV"
+ }, targetAnchor);
+ rightBottomDiv = html.create("div", {
+ "class": "dojoxGridCellBorderRightBottomDIV"
+ }, targetAnchor);
+ }else{
+ leftTopDiv = query(".dojoxGridCellBorderLeftTopDIV", targetAnchor)[0];
+ rightBottomDiv = query(".dojoxGridCellBorderRightBottomDIV", targetAnchor)[0];
+ }
+ for(i = s.min.col + 1; i < origin.col; ++i){
+ if(cells[i].hidden){
+ --preSpan;
+ }
+ }
+ for(i = origin.col + 1; i < s.max.col; ++i){
+ if(cells[i].hidden){
+ --postSpan;
+ }
+ }
+ headers = this._getVisibleHeaders();
+ //calc width
+ for(i = preSpan; i < headers.length - postSpan; ++i){
+ headPos = html.position(headers[i].node);
+ if((evt.clientX >= headPos.x && evt.clientX < headPos.x + headPos.w) || //within in this column
+ //prior to this column, but within range
+ (i == preSpan && (ltr ? evt.clientX < headPos.x : evt.clientX >= headPos.x + headPos.w)) ||
+ //post to this column, but within range
+ (i == headers.length - postSpan - 1 && (ltr ? evt.clientX >= headPos.x + headPos.w : evt < headPos.x))){
+ minCol = headers[i - preSpan];
+ maxCol = headers[i + postSpan];
+ minPos = html.position(minCol.node);
+ maxPos = html.position(maxCol.node);
+ minCol = minCol.cell.index;
+ maxCol = maxCol.cell.index;
+ left = ltr ? minPos.x : maxPos.x;
+ width = ltr ? (maxPos.x + maxPos.w - minPos.x) : (minPos.x + minPos.w - maxPos.x);
+ break;
+ }
+ }
+ //calc height
+ i = 0;
+ while(cells[i].hidden){ ++i; }
+ var cell = cells[i],
+ rowIndex = g.scroller.firstVisibleRow,
+ nodePos = html.position(cell.getNode(rowIndex));
+ while(nodePos.y + nodePos.h < evt.clientY){
+ if(++rowIndex < g.rowCount){
+ nodePos = html.position(cell.getNode(rowIndex));
+ }else{
+ break;
+ }
+ }
+ var minRow = rowIndex >= origin.row - s.min.row ? rowIndex - origin.row + s.min.row : 0;
+ var maxRow = minRow + s.max.row - s.min.row;
+ if(maxRow >= g.rowCount){
+ maxRow = g.rowCount - 1;
+ minRow = maxRow - s.max.row + s.min.row;
+ }
+ minPos = html.position(cell.getNode(minRow));
+ maxPos = html.position(cell.getNode(maxRow));
+ top = minPos.y;
+ height = maxPos.y + maxPos.h - minPos.y;
+ this._target = {
+ "min":{
+ "row": minRow,
+ "col": minCol
+ },
+ "max":{
+ "row": maxRow,
+ "col": maxCol
+ }
+ };
+ var anchorBorderSize = (html.marginBox(leftTopDiv).w - html.contentBox(leftTopDiv).w) / 2;
+ var leftTopCellPos = html.position(cells[minCol].getNode(minRow));
+ html.style(leftTopDiv, {
+ "width": (leftTopCellPos.w - anchorBorderSize) + "px",
+ "height": (leftTopCellPos.h - anchorBorderSize) + "px"
+ });
+ var rightBottomCellPos = html.position(cells[maxCol].getNode(maxRow));
+ html.style(rightBottomDiv, {
+ "width": (rightBottomCellPos.w - anchorBorderSize) + "px",
+ "height": (rightBottomCellPos.h - anchorBorderSize) + "px"
+ });
+ return {
+ h: height,
+ w: width,
+ l: left - containerPos.x,
+ t: top - containerPos.y
+ };
+ },
+ _markTargetAnchor: function(evt){
+ try{
+ var t = this._dndRegion.type;
+ if(this._alreadyOut || (this._dnding && !this._config[t]["within"]) || (this._extDnding && !this._config[t]["in"])){
+ return;
+ }
+ var height, width, left, top,
+ targetAnchor = this._targetAnchor[t],
+ pos = html.position(this._container);
+ if(!targetAnchor){
+ targetAnchor = this._targetAnchor[t] = html.create("div", {
+ "class": (t == "cell") ? "dojoxGridCellBorderDIV" : "dojoxGridBorderDIV"
+ });
+ html.style(targetAnchor, "display", "none");
+ this._container.appendChild(targetAnchor);
+ }
+ switch(t){
+ case "col":
+ height = pos.h;
+ width = this._targetAnchorBorderWidth;
+ left = this._calcColTargetAnchorPos(evt, pos);
+ top = 0;
+ break;
+ case "row":
+ height = this._targetAnchorBorderWidth;
+ width = pos.w;
+ left = 0;
+ top = this._calcRowTargetAnchorPos(evt, pos);
+ break;
+ case "cell":
+ var cellPos = this._calcCellTargetAnchorPos(evt, pos, targetAnchor);
+ height = cellPos.h;
+ width = cellPos.w;
+ left = cellPos.l;
+ top = cellPos.t;
+ }
+ if(typeof height == "number" && typeof width == "number" && typeof left == "number" && typeof top == "number"){
+ html.style(targetAnchor, {
+ "height": height + "px",
+ "width": width + "px",
+ "left": left + "px",
+ "top": top + "px"
+ });
+ html.style(targetAnchor, "display", "");
+ }else{
+ this._target = null;
+ }
+ }catch(e){
+ console.warn("DnD._markTargetAnchor() error:",e);
+ }
+ },
+ _unmarkTargetAnchor: function(){
+ if(this._dndRegion){
+ var targetAnchor = this._targetAnchor[this._dndRegion.type];
+ if(targetAnchor){
+ html.style(this._targetAnchor[this._dndRegion.type], "display", "none");
+ }
+ }
+ },
+ _getVisibleHeaders: function(){
+ return array.map(array.filter(this.grid.layout.cells, function(cell){
+ return !cell.hidden;
+ }), function(cell){
+ return {
+ "node": cell.getHeaderNode(),
+ "cell": cell
+ };
+ });
+ },
+ _rearrange: function(){
+ if(this._target === null){
+ return;
+ }
+ var t = this._dndRegion.type;
+ var ranges = this._dndRegion.selected;
+ if(t === "cell"){
+ this.rearranger[(this._isCopy || this._copyOnly) ? "copyCells" : "moveCells"](ranges[0], this._target === -1 ? null : this._target);
+ }else{
+ this.rearranger[t == "col" ? "moveColumns" : "moveRows"](_joinToArray(ranges), this._target === -1 ? null: this._target);
+ }
+ this._target = null;
+ },
+ onDraggingOver: function(sourcePlugin){
+ if(!this._dnding && sourcePlugin){
+ sourcePlugin._isSource = true;
+ this._extDnding = true;
+ if(!this._externalDnd){
+ this._externalDnd = true;
+ this._dndRegion = this._mapRegion(sourcePlugin.grid, sourcePlugin._dndRegion);
+ }
+ this._createDnDUI(this._moveEvent,true);
+ this.grid.pluginMgr.getPlugin("autoScroll").readyForAutoScroll = true;
+ }
+ },
+ _mapRegion: function(srcGrid, dndRegion){
+ if(dndRegion.type === "cell"){
+ var srcRange = dndRegion.selected[0];
+ var cells = this.grid.layout.cells;
+ var srcCells = srcGrid.layout.cells;
+ var c, cnt = 0;
+ for(c = srcRange.min.col; c <= srcRange.max.col; ++c){
+ if(!srcCells[c].hidden){
+ ++cnt;
+ }
+ }
+ for(c = 0; cnt > 0; ++c){
+ if(!cells[c].hidden){
+ --cnt;
+ }
+ }
+ var region = lang.clone(dndRegion);
+ region.selected[0].min.col = 0;
+ region.selected[0].max.col = c - 1;
+ for(c = srcRange.min.col; c <= dndRegion.handle.col; ++c){
+ if(!srcCells[c].hidden){
+ ++cnt;
+ }
+ }
+ for(c = 0; cnt > 0; ++c){
+ if(!cells[c].hidden){
+ --cnt;
+ }
+ }
+ region.handle.col = c;
+ }
+ return dndRegion;
+ },
+ onDraggingOut: function(sourcePlugin){
+ if(this._externalDnd){
+ this._extDnding = false;
+ this._destroyDnDUI(true, false);
+ if(sourcePlugin){
+ sourcePlugin._isSource = false;
+ }
+ }
+ },
+ onDragIn: function(sourcePlugin, isCopy){
+ var success = false;
+ if(this._target !== null){
+ var type = sourcePlugin._dndRegion.type;
+ var ranges = sourcePlugin._dndRegion.selected;
+ switch(type){
+ case "cell":
+ this.rearranger.changeCells(sourcePlugin.grid, ranges[0], this._target);
+ break;
+ case "row":
+ var range = _joinToArray(ranges);
+ this.rearranger.insertRows(sourcePlugin.grid, range, this._target);
+ break;
+ }
+ success = true;
+ }
+ this._endDnd(true);
+ if(sourcePlugin.onDragOut){
+ sourcePlugin.onDragOut(success && !isCopy);
+ }
+ },
+ onDragOut: function(isMove){
+ if(isMove && !this._copyOnly){
+ var type = this._dndRegion.type;
+ var ranges = this._dndRegion.selected;
+ switch(type){
+ case "cell":
+ this.rearranger.clearCells(ranges[0]);
+ break;
+ case "row":
+ this.rearranger.removeRows(_joinToArray(ranges));
+ break;
+ }
+ }
+ this._endDnd(true);
+ },
+ _canAccept: function(sourcePlugin){
+ if(!sourcePlugin){
+ return false;
+ }
+ var srcRegion = sourcePlugin._dndRegion;
+ var type = srcRegion.type;
+ if(!this._config[type]["in"] || !sourcePlugin._config[type]["out"]){
+ return false;
+ }
+ var g = this.grid;
+ var ranges = srcRegion.selected;
+ var colCnt = array.filter(g.layout.cells, function(cell){
+ return !cell.hidden;
+ }).length;
+ var rowCnt = g.rowCount;
+ var res = true;
+ switch(type){
+ case "cell":
+ ranges = ranges[0];
+ res = g.store.getFeatures()["dojo.data.api.Write"] &&
+ (ranges.max.row - ranges.min.row) <= rowCnt &&
+ array.filter(sourcePlugin.grid.layout.cells, function(cell){
+ return cell.index >= ranges.min.col && cell.index <= ranges.max.col && !cell.hidden;
+ }).length <= colCnt;
+ //intentional drop through - don't break
+ case "row":
+ if(sourcePlugin._allDnDItemsLoaded()){
+ return res;
+ }
+ }
+ return false;
+ },
+ _allDnDItemsLoaded: function(){
+ if(this._dndRegion){
+ var type = this._dndRegion.type,
+ ranges = this._dndRegion.selected,
+ rows = [];
+ switch(type){
+ case "cell":
+ for(var i = ranges[0].min.row, max = ranges[0].max.row; i <= max; ++i){
+ rows.push(i);
+ }
+ break;
+ case "row":
+ rows = _joinToArray(ranges);
+ break;
+ default:
+ return false;
+ }
+ var cache = this.grid._by_idx;
+ return array.every(rows, function(rowIndex){
+ return !!cache[rowIndex];
+ });
+ }
+ return false;
+ }
+});
+
+EnhancedGrid.registerPlugin(DnD/*name:'dnd'*/, {
+ "dependency": ["selector", "rearrange"]
+});
+
+return DnD;
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/Exporter.js b/js/dojo/dojox/grid/enhanced/plugins/Exporter.js
new file mode 100644
index 0000000..fe12206
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/Exporter.js
@@ -0,0 +1,243 @@
+//>>built
+define("dojox/grid/enhanced/plugins/Exporter", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/lang",
+ "../_Plugin",
+ "../../_RowSelector",
+ "../../EnhancedGrid",
+ "../../cells/_base"
+], function(declare, array, lang, _Plugin, _RowSelector, EnhancedGrid){
+
+var gridCells = lang.getObject("dojox.grid.cells");
+
+var Exporter = declare("dojox.grid.enhanced.plugins.Exporter", _Plugin, {
+ // summary:
+ // Provide functions to export the grid data into a given format.
+ //
+ // Acceptable plugin parameters:
+ // 1. exportFormatter: function(data, cell, rowIndex, item)
+ // Provide a way to customize how data should look in exported string.
+ // Note that usually the formatter of grid cell should not be used here (it can return HTML or even widget).
+ // example:
+ // | function onExported(exported_text){
+ // | //custom code here...
+ // | }
+ // | dijit.byId("my_grid_id").exportTo("csv", //registered export format, mandatory
+ // | { //the whole object is optional.
+ // | fetchArgs: {start:0,count:1000}, //keywordArgs for fetch, optional
+ // | writerArgs: {separator:';'}, //export writer specific arguments, optional
+ // | },
+ // | function(str){
+ // | //call back function, mandatory
+ // | });
+ // | var result = dijit.byId("my_grid_id").exportSelectedTo("table", //registered export format, mandatory
+ // | {separator:'|'} //export writer specific arguments, optional
+ // | );
+ //
+
+ // name: String
+ // Plugin name.
+ name: "exporter",
+
+ constructor: function(grid, args){
+ // summary:
+ // only newed by _Plugin
+ // grid: EnhancedGrid
+ // The grid to plug in to.
+ this.grid = grid;
+ this.formatter = (args && lang.isObject(args)) && args.exportFormatter;
+ this._mixinGrid();
+ },
+ _mixinGrid: function(){
+ var g = this.grid;
+ g.exportTo = lang.hitch(this, this.exportTo);
+ g.exportGrid = lang.hitch(this, this.exportGrid);
+ g.exportSelected = lang.hitch(this, this.exportSelected);
+ g.setExportFormatter = lang.hitch(this, this.setExportFormatter);
+ },
+ setExportFormatter: function(formatter){
+ this.formatter = formatter;
+ },
+ exportGrid: function(type, args, onExported){
+ // summary:
+ // Export required rows(fetchArgs) to a kind of format(type)
+ // using the corresponding writer with given arguments(writerArgs),
+ // then pass the exported text to a given function(onExported).
+ // tags:
+ // public
+ // type: string
+ // A registered export format name
+ // args: object?
+ // includes:
+ // {
+ // fetchArgs: object?
+ // Any arguments for store.fetch
+ // writerArgs: object?
+ // Arguments for the given format writer
+ // }
+ // onExported: function(string)
+ // Call back function when export result is ready
+ if(lang.isFunction(args)){
+ onExported = args;
+ args = {};
+ }
+ if(!lang.isString(type) || !lang.isFunction(onExported)){
+ return;
+ }
+ args = args || {};
+ var g = this.grid, _this = this,
+ writer = this._getExportWriter(type, args.writerArgs),
+ fetchArgs = (args.fetchArgs && lang.isObject(args.fetchArgs)) ? args.fetchArgs : {},
+ oldFunc = fetchArgs.onComplete;
+ if(g.store){
+ fetchArgs.onComplete = function(items, request){
+ if(oldFunc){
+ oldFunc(items, request);
+ }
+ onExported(_this._goThroughGridData(items, writer));
+ };
+ fetchArgs.sort = fetchArgs.sort || g.getSortProps();
+ g._storeLayerFetch(fetchArgs);
+ }else{
+ //Data is defined directly in the structure;
+ var start = fetchArgs.start || 0,
+ count = fetchArgs.count || -1,
+ items = [];
+ for(var i = start; i != start + count && i < g.rowCount; ++i){
+ items.push(g.getItem(i));
+ }
+ onExported(this._goThroughGridData(items, writer));
+ }
+ },
+ exportSelected: function(type, writerArgs){
+ // summary:
+ // Only export selected rows.
+ // tags:
+ // public
+ // type: string
+ // A registered export format name
+ // writerArgs: object?
+ // Arguments for the given format writer
+ // returns: string
+ // The exported string
+ if(!lang.isString(type)){
+ return "";
+ }
+ var writer = this._getExportWriter(type, writerArgs);
+ return this._goThroughGridData(this.grid.selection.getSelected(), writer); //String
+ },
+ _buildRow: function(/* object */arg_obj,/* ExportWriter */writer){
+ // summary:
+ // Use the given export writer(writer) to go through a single row
+ // which is given in the context object(arg_obj).
+ // tags:
+ // private
+ // returns:
+ // undefined
+ var _this = this;
+ array.forEach(arg_obj._views, function(view, vIdx){
+ arg_obj.view = view;
+ arg_obj.viewIdx = vIdx;
+ if(writer.beforeView(arg_obj)){
+ array.forEach(view.structure.cells, function(subrow, srIdx){
+ arg_obj.subrow = subrow;
+ arg_obj.subrowIdx = srIdx;
+ if(writer.beforeSubrow(arg_obj)){
+ array.forEach(subrow, function(cell, cIdx){
+ if(arg_obj.isHeader && _this._isSpecialCol(cell)){
+ arg_obj.spCols.push(cell.index);
+ }
+ arg_obj.cell = cell;
+ arg_obj.cellIdx = cIdx;
+ writer.handleCell(arg_obj);
+ });
+ writer.afterSubrow(arg_obj);
+ }
+ });
+ writer.afterView(arg_obj);
+ }
+ });
+ },
+ _goThroughGridData: function(/* Array */items,/* ExportWriter */writer){
+ // summary:
+ // Use the given export writer(writer) to go through the grid structure
+ // and the given rows(items), then return the writer output.
+ // tags:
+ // private
+ var grid = this.grid,
+ views = array.filter(grid.views.views, function(view){
+ return !(view instanceof _RowSelector);
+ }),
+ arg_obj = {
+ 'grid': grid,
+ 'isHeader': true,
+ 'spCols': [],
+ '_views': views,
+ 'colOffset': (views.length < grid.views.views.length ? -1 : 0)
+ };
+ //go through header
+ if(writer.beforeHeader(grid)){
+ this._buildRow(arg_obj,writer);
+ writer.afterHeader();
+ }
+ //go through content
+ arg_obj.isHeader = false;
+ if(writer.beforeContent(items)){
+ array.forEach(items, function(item, rIdx){
+ arg_obj.row = item;
+ arg_obj.rowIdx = rIdx;
+ if(writer.beforeContentRow(arg_obj)){
+ this._buildRow(arg_obj, writer);
+ writer.afterContentRow(arg_obj);
+ }
+ }, this);
+ writer.afterContent();
+ }
+ return writer.toString();
+ },
+ _isSpecialCol: function(/* dojox.grid.__CellDef */header_cell){
+ // summary:
+ // Row selectors and row indexes should be recognized and handled separately.
+ // tags:
+ // private
+ return header_cell.isRowSelector || header_cell instanceof gridCells.RowIndex; //Boolean
+ },
+ _getExportWriter: function(/* string */ fileType, /* object? */ writerArgs){
+ // summary:
+ // Use the given export format type(fileType)
+ // and writer arguments(writerArgs) to create
+ // a ExportWriter and return it.
+ // tags:
+ // private
+ var writerName, cls,
+ expCls = Exporter;
+ if(expCls.writerNames){
+ writerName = expCls.writerNames[fileType.toLowerCase()];
+ cls = lang.getObject(writerName);
+ if(cls){
+ var writer = new cls(writerArgs);
+ writer.formatter = this.formatter;
+ return writer; //ExportWriter
+ }else{
+ throw new Error('Please make sure class "' + writerName + '" is required.');
+ }
+ }
+ throw new Error('The writer for "' + fileType + '" has not been registered.');
+ }
+});
+
+Exporter.registerWriter = function(/* string */fileType,/* string */writerClsName){
+ // summary:
+ // Register a writer(writerClsName) to a export format type(fileType).
+ // This function separates the Exporter from all kinds of writers.
+ // tags:
+ // public
+ Exporter.writerNames = Exporter.writerNames || {};
+ Exporter.writerNames[fileType] = writerClsName;
+};
+
+EnhancedGrid.registerPlugin(Exporter/*name:'exporter'*/);
+
+return Exporter;
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/Filter.js b/js/dojo/dojox/grid/enhanced/plugins/Filter.js
new file mode 100644
index 0000000..a68a00f
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/Filter.js
@@ -0,0 +1,173 @@
+//>>built
+define("dojox/grid/enhanced/plugins/Filter", [
+ "dojo/_base/declare",
+ "dojo/_base/lang",
+ "dojo/i18n",
+ "../_Plugin",
+ "./Dialog",
+ "./filter/FilterLayer",
+ "./filter/FilterBar",
+ "./filter/FilterDefDialog",
+ "./filter/FilterStatusTip",
+ "./filter/ClearFilterConfirm",
+ "../../EnhancedGrid",
+ "dojo/i18n!../nls/Filter"
+], function(declare, lang, i18n, _Plugin, Dialog, layers, FilterBar, FilterDefDialog, FilterStatusTip, ClearFilterConfirm, EnhancedGrid){
+
+ var Filter = declare("dojox.grid.enhanced.plugins.Filter", _Plugin, {
+ // summary:
+ // Provide filter functionality for grid.
+ //
+ // Acceptable plugin parameters:
+ // 1. itemsName: string
+ // the name shown on the filter bar.
+ // 2. statusTipTimeout: number
+ // when does the status tip show.
+ // 3. ruleCount: number
+ // default to 3, should not change to more. The Claro theme limits it.
+ // 4. disabledConditions: object
+ // If you don't need all of the conditions provided for a data type,
+ // you can explicitly declare them here:
+ // e.g.: disabledConditions: {string: ["contains", "is"], number: ["equalto"], ...}
+ // 5. isServerSide: boolean
+ // Whether to use server side filtering. Default to false.
+ // 6. isStateful: boolean
+ // If isServerSide is true, set the server side filter to be stateful or not. default to false.
+ // 7. url: string
+ // If using stateful, this is the url to send commands. default to store.url.
+ // 8. ruleCountToConfirmClearFilter: Integer | null |Infinity
+ // If the filter rule count is larger than or equal to this value, then a confirm dialog will show when clearing filter.
+ // If set to less than 1 or null, then always show the confirm dialog.
+ // If set to Infinity, then never show the confirm dialog.
+ // Default value is 2.
+ //
+ // Acceptable cell parameters defined in layout:
+ // 1. filterable: boolean
+ // The column is not filterable only when this is set to false explicitly.
+ // 2. datatype: string
+ // The data type of this column. Can be "string", "number", "date", "time", "boolean".
+ // Default to "string".
+ // 3. autoComplete: boolean
+ // If need auto-complete in the ComboBox for String type, set this to true.
+ // 4. dataTypeArgs: object
+ // Some arguments helping convert store data to something the filter UI understands.
+ // Different data type arguments can be provided to different data types.
+ // For date/time, this is a dojo.date.locale.__FormatOptions, so the DataTimeBox can understand the store data.
+ // For boolean, this object contains:
+ // trueLabel: string
+ // A label to display in the filter definition dialog for true value. Default to "True".
+ // falseLable: string
+ // A label to display in the filter definition dialog for false value. Default to "False".
+ // 5. disabledConditions: object
+ // If you don't need all of the conditions provided by the filter UI on this column, you can explicitly say it out here.
+ // e.g.: disabledConditions: ["contains", "is"]
+ // This will disable the "contains" condition for this column, if this column is of string type.
+ // For full set of conditions, please refer to dojox.grid.enhanced.plugins.filter.FilterDefDialog._setupData.
+ // example:
+ // | <div dojoType="dojox.grid.EnhancedGrid" plugins="{GridFilter: true}" ...></div>
+ // | or provide some parameters:
+ // | <div dojoType="dojox.grid.EnhancedGrid" plugins="{GridFilter: {itemsName: 'songs'}}" ...></div>
+ // | Customize columns for filter:
+ // | var layout = [
+ // | ...
+ // | //define a column to be un-filterable in layout/structure
+ // | {field: "Genre", filterable: false, ...}
+ // | //define a column of type string and supports autoComplete when you type in filter conditions.
+ // | {field: "Writer", datatype: "string", autoCommplete: true, ...}
+ // | //define a column of type date and the data in store has format: "yyyy/M/d"
+ // | {field: "Publish Date", datatype: "date", dataTypeArgs: {datePattern: "yyyy/M/d"}, ...}
+ // | //disable some conditions for a column
+ // | {field: "Track", disabledConditions: ["equalto","notequalto"], ...}
+ // | ...
+ // | ];
+
+ // name: String
+ // plugin name
+ name: "filter",
+
+ constructor: function(grid, args){
+ // summary:
+ // See constructor of dojox.grid.enhanced._Plugin.
+ this.grid = grid;
+ this.nls = i18n.getLocalization("dojox.grid.enhanced", "Filter");
+
+ args = this.args = lang.isObject(args) ? args : {};
+ if(typeof args.ruleCount != 'number' || args.ruleCount < 0){
+ args.ruleCount = 3;
+ }
+ var rc = this.ruleCountToConfirmClearFilter = args.ruleCountToConfirmClearFilter;
+ if(rc === undefined){
+ this.ruleCountToConfirmClearFilter = 2;
+ }
+
+ //Install filter layer
+ this._wrapStore();
+
+ //Install UI components
+ var obj = { "plugin": this };
+ this.clearFilterDialog = new Dialog({
+ refNode: this.grid.domNode,
+ title: this.nls["clearFilterDialogTitle"],
+ content: new ClearFilterConfirm(obj)
+ });
+ this.filterDefDialog = new FilterDefDialog(obj);
+ this.filterBar = new FilterBar(obj);
+ this.filterStatusTip = new FilterStatusTip(obj);
+
+ //Expose the layer event to grid.
+ grid.onFilterDefined = function(){};
+ this.connect(grid.layer("filter"), "onFilterDefined", function(filter){
+ grid.onFilterDefined(grid.getFilter(), grid.getFilterRelation());
+ });
+ },
+ destroy: function(){
+ this.inherited(arguments);
+ try{
+ this.grid.unwrap("filter");
+ this.filterBar.destroyRecursive();
+ this.filterBar = null;
+ this.clearFilterDialog.destroyRecursive();
+ this.clearFilterDialog = null;
+ this.filterStatusTip.destroy();
+ this.filterStatusTip = null;
+ this.filterDefDialog.destroy();
+ this.filterDefDialog = null;
+ this.grid = null;
+ this.nls = null;
+ this.args = null;
+ }catch(e){
+ console.warn("Filter.destroy() error:",e);
+ }
+ },
+ _wrapStore: function(){
+ var g = this.grid;
+ var args = this.args;
+ var filterLayer = args.isServerSide ? new layers.ServerSideFilterLayer(args) :
+ new layers.ClientSideFilterLayer({
+ cacheSize: args.filterCacheSize,
+ fetchAll: args.fetchAllOnFirstFilter,
+ getter: this._clientFilterGetter
+ });
+ layers.wrap(g, "_storeLayerFetch", filterLayer);
+
+ this.connect(g, "_onDelete", lang.hitch(filterLayer, "invalidate"));
+ },
+ onSetStore: function(store){
+ this.filterDefDialog.clearFilter(true);
+ },
+ _clientFilterGetter: function(/* data item */ datarow,/* cell */cell, /* int */rowIndex){
+ // summary:
+ // Define the grid-specific way to get data from a row.
+ // Argument "cell" is provided by FilterDefDialog when defining filter expressions.
+ // Argument "rowIndex" is provided by FilterLayer when checking a row.
+ // FilterLayer also provides a forth argument: "store", which is grid.store,
+ // but we don't need it here.
+ return cell.get(rowIndex, datarow);
+ }
+ });
+
+ EnhancedGrid.registerPlugin(Filter/*name:'filter'*/);
+
+ return Filter;
+
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/GridSource.js b/js/dojo/dojox/grid/enhanced/plugins/GridSource.js
new file mode 100644
index 0000000..18c393c
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/GridSource.js
@@ -0,0 +1,155 @@
+//>>built
+define("dojox/grid/enhanced/plugins/GridSource", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/lang",
+ "dojo/dnd/Source",
+ "./DnD"
+], function(declare, array, lang, Source, DnD){
+
+var _joinToArray = function(arrays){
+ var a = arrays[0];
+ for(var i = 1; i < arrays.length; ++i){
+ a = a.concat(arrays[i]);
+ }
+ return a;
+};
+
+var GridDnDSource = lang.getObject("dojox.grid.enhanced.plugins.GridDnDSource");
+
+return declare("dojox.grid.enhanced.plugins.GridSource", Source, {
+ // summary:
+ // A special source that can accept grid contents.
+ // Only for non-grid widgets or domNodes.
+ accept: ["grid/cells", "grid/rows", "grid/cols", "text"],
+
+ // insertNodesForGrid:
+ // If you'd like to insert some sort of nodes into your dnd source, turn this on,
+ // and override getCellContent/getRowContent/getColumnContent
+ // to populate the dnd data in your desired format.
+ insertNodesForGrid: false,
+
+ markupFactory: function(params, node){
+ cls = lang.getObject("dojox.grid.enhanced.plugins.GridSource");
+ return new cls(node, params);
+ },
+ checkAcceptance: function(source, nodes){
+ if(source instanceof GridDnDSource){
+ if(nodes[0]){
+ var item = source.getItem(nodes[0].id);
+ if(item && (array.indexOf(item.type, "grid/rows") >= 0 || array.indexOf(item.type, "grid/cells") >= 0) &&
+ !source.dndPlugin._allDnDItemsLoaded()){
+ return false;
+ }
+ }
+ this.sourcePlugin = source.dndPlugin;
+ }
+ return this.inherited(arguments);
+ },
+ onDraggingOver: function(){
+ if(this.sourcePlugin){
+ this.sourcePlugin._isSource = true;
+ }
+ },
+ onDraggingOut: function(){
+ if(this.sourcePlugin){
+ this.sourcePlugin._isSource = false;
+ }
+ },
+ onDropExternal: function(source, nodes, copy){
+ if(source instanceof GridDnDSource){
+ var ranges = array.map(nodes, function(node){
+ return source.getItem(node.id).data;
+ });
+ var item = source.getItem(nodes[0].id);
+ var grid = item.dndPlugin.grid;
+ var type = item.type[0];
+ var range;
+ try{
+ switch(type){
+ case "grid/cells":
+ nodes[0].innerHTML = this.getCellContent(grid, ranges[0].min, ranges[0].max) || "";
+ this.onDropGridCells(grid, ranges[0].min, ranges[0].max);
+ break;
+ case "grid/rows":
+ range = _joinToArray(ranges);
+ nodes[0].innerHTML = this.getRowContent(grid, range) || "";
+ this.onDropGridRows(grid, range);
+ break;
+ case "grid/cols":
+ range = _joinToArray(ranges);
+ nodes[0].innerHTML = this.getColumnContent(grid, range) || "";
+ this.onDropGridColumns(grid, range);
+ break;
+ }
+ if(this.insertNodesForGrid){
+ this.selectNone();
+ this.insertNodes(true, [nodes[0]], this.before, this.current);
+ }
+ item.dndPlugin.onDragOut(!copy);
+ }catch(e){
+ console.warn("GridSource.onDropExternal() error:",e);
+ }
+ }else{
+ this.inherited(arguments);
+ }
+ },
+ getCellContent: function(grid, leftTopCell, rightBottomCell){
+ // summary:
+ // Fill node innerHTML for dnd grid cells.
+ // sample code:
+ // var cells = grid.layout.cells;
+ // var store = grid.store;
+ // var cache = grid._by_idx;
+ // var res = "Grid Cells from " + grid.id + ":<br/>";
+ // for(var r = leftTopCell.row; r <= rightBottomCell.row; ++r){
+ // for(var c = leftTopCell.col; c <= rightBottomCell.col; ++c){
+ // res += store.getValue(cache[r].item, cells[c].field) + ", ";
+ // }
+ // res = res.substring(0, res.length - 2) + ";<br/>";
+ // }
+ // return res;
+ },
+ getRowContent: function(grid, rowIndexes){
+ // summary:
+ // Fill node innerHTML for dnd grid rows.
+ // sample code:
+ // var cells = grid.layout.cells;
+ // var store = grid.store;
+ // var cache = grid._by_idx;
+ // var res = "Grid Rows from " + grid.id + ":<br/>";
+ // for(var i = 0; i < rowIndexes.length; ++i){
+ // var r = rowIndexes[i];
+ // res += "Row " + r + ": ";
+ // for(var j = 0; j < cells.length; ++j){
+ // if(!cells[j].hidden){
+ // res += store.getValue(cache[r].item, cells[j].field) + ", ";
+ // }
+ // }
+ // res = res.substring(0, res.length - 2) + ";<br/>";
+ // }
+ // return res;
+ },
+ getColumnContent: function(grid, colIndexes){
+ // summary:
+ // Fill node innerHTML for dnd grid columns.
+ // sample code:
+ // var cells = grid.layout.cells;
+ // var res = "Grid Columns from " + grid.id + ":";
+ // for(var i = 0; i < colIndexes.length; ++i){
+ // var c = colIndexes[i];
+ // res += (cells[c].name || cells[c].field) + ", ";
+ // }
+ // return res.substring(0, res.length - 2);
+ },
+ onDropGridCells: function(grid, leftTopCell, rightBottomCell){
+
+ },
+ onDropGridRows: function(grid, rowIndexes){
+
+ },
+ onDropGridColumns: function(grid, colIndexes){
+
+ }
+});
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/IndirectSelection.js b/js/dojo/dojox/grid/enhanced/plugins/IndirectSelection.js
new file mode 100644
index 0000000..3b41e84
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/IndirectSelection.js
@@ -0,0 +1,626 @@
+//>>built
+define("dojox/grid/enhanced/plugins/IndirectSelection", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ "dojo/_base/lang",
+ "dojo/_base/html",
+ "dojo/_base/window",
+ "dojo/_base/connect",
+ "dojo/_base/sniff",
+ "dojo/query",
+ "dojo/keys",
+ "dojo/string",
+ "../_Plugin",
+ "../../EnhancedGrid",
+ "../../cells/dijit"
+], function(declare, array, evt, lang, html, win, connect, has, query, keys, string, _Plugin, EnhancedGrid){
+
+var gridCells = lang.getObject("dojox.grid.cells");
+
+var RowSelector = declare("dojox.grid.cells.RowSelector", gridCells._Widget, {
+ // summary:
+ // Common attributes & functions for row selectors(Radio|CheckBox)
+
+ //inputType: String
+ // Input type - Radio|CheckBox
+ inputType: "",
+
+ //map: Object
+ // Cache div refs of radio|checkbox to avoid querying each time
+ map: null,
+
+ //disabledMap: Object
+ // Cache index of disabled rows
+ disabledMap: null,
+
+ //isRowSelector: Boolean
+ // Marker of indirectSelection cell(column)
+ isRowSelector: true,
+
+ //_connects: Array
+ // List of all connections.
+ _connects: null,
+
+ //_subscribes: Array
+ // List of all subscribes.
+ _subscribes: null,
+
+ //checkedText: String
+ // Checked character for high contrast mode
+ checkedText: '&#10003;',
+
+ //unCheckedText: String
+ // Unchecked character for high contrast mode
+ unCheckedText: 'O',
+
+ constructor: function(){
+ this.map = {}; this.disabledMap = {}, this.disabledCount= 0;
+ this._connects = []; this._subscribes = [];
+ this.inA11YMode = html.hasClass(win.body(), "dijit_a11y");
+
+ this.baseClass = "dojoxGridRowSelector dijitReset dijitInline dijit" + this.inputType;
+ this.checkedClass = " dijit" + this.inputType + "Checked";
+ this.disabledClass = " dijit" + this.inputType + "Disabled";
+ this.checkedDisabledClass = " dijit" + this.inputType + "CheckedDisabled";
+ this.statusTextClass = " dojoxGridRowSelectorStatusText";//a11y use
+
+ this._connects.push(connect.connect(this.grid, 'dokeyup', this, '_dokeyup'));
+ this._connects.push(connect.connect(this.grid.selection, 'onSelected', this, '_onSelected'));
+ this._connects.push(connect.connect(this.grid.selection, 'onDeselected', this, '_onDeselected'));
+ this._connects.push(connect.connect(this.grid.scroller, 'invalidatePageNode', this, '_pageDestroyed'));
+ this._connects.push(connect.connect(this.grid, 'onCellClick', this, '_onClick'));
+ this._connects.push(connect.connect(this.grid, 'updateRow', this, '_onUpdateRow'));
+ },
+ formatter: function(data, rowIndex, scope){
+ // summary:
+ // Overwritten, see dojox.grid.cells._Widget
+ var _this = scope;
+ var clazz = _this.baseClass;
+ var checked = _this.getValue(rowIndex);
+ var disabled = !!_this.disabledMap[rowIndex];//normalize 'undefined'
+
+ if(checked){
+ clazz += _this.checkedClass;
+ if(disabled){ clazz += _this.checkedDisabledClass; }
+ }else if(disabled){
+ clazz += _this.disabledClass;
+ }
+ return ["<div tabindex = -1 ",
+ "id = '" + _this.grid.id + "_rowSelector_" + rowIndex + "' ",
+ "name = '" + _this.grid.id + "_rowSelector' class = '" + clazz + "' ",
+ "role = 'presentation' aria-pressed = '" + checked + "' aria-disabled = '" + disabled +
+ "' aria-label = '" + string.substitute(_this.grid._nls["indirectSelection" + _this.inputType], [rowIndex + 1]) + "'>",
+ "<span class = '" + _this.statusTextClass + "'>" + (checked ? _this.checkedText : _this.unCheckedText) + "</span>",
+ "</div>"].join("");
+ },
+ setValue: function(rowIndex, inValue){
+ // summary:
+ // Overwritten, see dojox.grid.cells._Widget
+ // Simply return, no action
+ },
+ getValue: function(rowIndex){
+ // summary:
+ // Overwritten, see dojox.grid.cells._Widget
+ return this.grid.selection.isSelected(rowIndex);
+ },
+ toggleRow: function(index, value){
+ // summary:
+ // toggle checked | unchecked state for given row
+ // index: Integer
+ // Row index
+ // value: Boolean
+ // True - checked | False - unchecked
+ this._nativeSelect(index, value);
+ },
+ setDisabled: function(index, disabled){
+ // summary:
+ // toggle disabled | enabled state for given row
+ // idx: Integer
+ // Row index
+ // disabled: Boolean
+ // True - disabled | False - enabled
+ if(index < 0){ return; }
+ this._toggleDisabledStyle(index, disabled);
+ },
+ disabled: function(index){
+ // summary:
+ // Check if one row is disabled
+ return !!this.disabledMap[index];
+ },
+ _onClick: function(e){
+ // summary:
+ // When mouse click on the selector cell, select/deselect the row.
+ if(e.cell === this){
+ this._selectRow(e);
+ }
+ },
+ _dokeyup: function(e){
+ // summary:
+ // Event handler for key up event
+ // - from dojox.grid.enhanced._Events.dokeyup()
+ // e: Event
+ // Key up event
+ if(e.cellIndex == this.index && e.rowIndex >= 0 && e.keyCode == keys.SPACE){
+ this._selectRow(e);
+ }
+ },
+ focus: function(rowIndex){
+ // summary:
+ // Set focus to given row
+ // rowIndex: Integer
+ // Target row
+ var selector = this.map[rowIndex];
+ if(selector){ selector.focus(); }
+ },
+ _focusEndingCell: function(rowIndex, cellIndex){
+ // summary:
+ // Set focus to the ending grid cell(rowIndex,cellIndex) when swipe selection finished
+ // rowIndex: Integer
+ // Row index
+ // cellIndex: Integer
+ // Column index
+ var cell = this.grid.getCell(cellIndex);
+ this.grid.focus.setFocusCell(cell, rowIndex);
+ },
+ _nativeSelect: function(index, value){
+ // summary:
+ // Use grid's native selection
+ this.grid.selection[value ? 'select' : 'deselect'](index);
+ },
+ _onSelected: function(index){
+ // summary:
+ // Triggered when a row is selected
+ this._toggleCheckedStyle(index, true);
+ },
+ _onDeselected: function(index){
+ // summary:
+ // Triggered when a row is deselected
+ this._toggleCheckedStyle(index, false);
+ },
+ _onUpdateRow: function(index){
+ // summary:
+ // Clear cache when row is re-built.
+ delete this.map[index];
+ },
+ _toggleCheckedStyle: function(index, value){
+ // summary:
+ // Change css styles for checked | unchecked
+ var selector = this._getSelector(index);
+ if(selector){
+ html.toggleClass(selector, this.checkedClass, value);
+ if(this.disabledMap[index]){
+ html.toggleClass(selector, this.checkedDisabledClass, value);
+ }
+ selector.setAttribute("aria-pressed", value);
+ if(this.inA11YMode){
+ selector.firstChild.innerHTML = (value ? this.checkedText : this.unCheckedText);
+ }
+ }
+ },
+ _toggleDisabledStyle: function(index, disabled){
+ // summary:
+ // Change css styles for disabled | enabled
+ var selector = this._getSelector(index);
+ if(selector){
+ html.toggleClass(selector, this.disabledClass, disabled);
+ if(this.getValue(index)){
+ html.toggleClass(selector, this.checkedDisabledClass, disabled);
+ }
+ selector.setAttribute("aria-disabled", disabled);
+ }
+ this.disabledMap[index] = disabled;
+ if(index >= 0){
+ this.disabledCount += disabled ? 1 : -1;
+ }
+ },
+ _getSelector: function(index){
+ // summary:
+ // Find selector for given row caching it if 1st time found
+ var selector = this.map[index];
+ if(!selector){//use accurate query for better performance
+ var rowNode = this.view.rowNodes[index];
+ if(rowNode){
+ selector = query('.dojoxGridRowSelector', rowNode)[0];
+ if(selector){ this.map[index] = selector; }
+ }
+ }
+ return selector;
+ },
+ _pageDestroyed: function(pageIndex){
+ // summary:
+ // Explicitly empty map cache when a page destroyed
+ // See dojox.grid._Scroller.invalidatePageNode()
+ // pageIndex: Integer
+ // Index of destroyed page
+ var rowsPerPage = this.grid.scroller.rowsPerPage;
+ var start = pageIndex * rowsPerPage, end = start + rowsPerPage - 1;
+ for(var i = start; i <= end; i++){
+ if(!this.map[i]){continue;}
+ html.destroy(this.map[i]);
+ delete this.map[i];
+ }
+ //console.log("Page ",pageIndex, " destroyed, Map=",this.map);
+ },
+ destroy: function(){
+ for(var i in this.map){
+ html.destroy(this.map[i]);
+ delete this.map[i];
+ }
+ for(i in this.disabledMap){ delete this.disabledMap[i]; }
+ array.forEach(this._connects, connect.disconnect);
+ array.forEach(this._subscribes, connect.unsubscribe);
+ delete this._connects;
+ delete this._subscribes;
+ //console.log('Single(Multiple)RowSelector.destroy() executed!');
+ }
+});
+
+var SingleRowSelector = declare("dojox.grid.cells.SingleRowSelector", RowSelector, {
+ // summary:
+ // IndirectSelection cell(column) for single selection mode, using styles of dijit.form.RadioButton
+ inputType: "Radio",
+
+ _selectRow: function(e){
+ // summary:
+ // Select the target row
+ // e: Event
+ // Event fired on the target row
+ var index = e.rowIndex;
+ if(this.disabledMap[index]){ return; }
+ this._focusEndingCell(index, 0);
+ this._nativeSelect(index, !this.grid.selection.selected[index]);
+ }
+});
+
+var MultipleRowSelector = declare("dojox.grid.cells.MultipleRowSelector", RowSelector, {
+ // summary:
+ // Indirect selection cell for multiple or extended mode, using dijit.form.CheckBox
+ inputType: "CheckBox",
+
+ //swipeStartRowIndex: Integer
+ // Start row index for swipe selection
+ swipeStartRowIndex: -1,
+
+ //swipeMinRowIndex: Integer
+ // Min row index for swipe selection
+ swipeMinRowIndex: -1,
+
+ //swipeMinRowIndex: Integer
+ // Max row index for swipe selection
+ swipeMaxRowIndex: -1,
+
+ //toSelect: Boolean
+ // new state for selection
+ toSelect: false,
+
+ //lastClickRowIdx: Integer
+ // Row index for last click, used for range selection via Shift + click
+ lastClickRowIdx: -1,
+
+ //toggleAllTrigerred: Boolean
+ // Whether toggle all has been triggered or not
+ toggleAllTrigerred: false,
+
+ unCheckedText: '&#9633;',
+
+ constructor: function(){
+ this._connects.push(connect.connect(win.doc, 'onmouseup', this, '_domouseup'));
+ this._connects.push(connect.connect(this.grid, 'onRowMouseOver', this, '_onRowMouseOver'));
+ this._connects.push(connect.connect(this.grid.focus, 'move', this, '_swipeByKey'));
+ this._connects.push(connect.connect(this.grid, 'onCellMouseDown', this, '_onMouseDown'));
+ if(this.headerSelector){//option set by user to add a select-all checkbox in column header
+ this._connects.push(connect.connect(this.grid.views, 'render', this, '_addHeaderSelector'));
+ this._connects.push(connect.connect(this.grid, '_onFetchComplete', this, '_addHeaderSelector'));
+ this._connects.push(connect.connect(this.grid, 'onSelectionChanged', this, '_onSelectionChanged'));
+ this._connects.push(connect.connect(this.grid, 'onKeyDown', this, function(e){
+ if(e.rowIndex == -1 && e.cellIndex == this.index && e.keyCode == keys.SPACE){
+ this._toggletHeader();//TBD - a better way
+ }
+ }));
+ }
+ },
+ toggleAllSelection:function(checked){
+ // summary:
+ // Toggle select all|deselect all
+ // checked: Boolean
+ // True - select all, False - deselect all
+ var grid = this.grid, selection = grid.selection;
+ if(checked){
+ selection.selectRange(0, grid.rowCount-1);
+ }else{
+ selection.deselectAll();
+ }
+ this.toggleAllTrigerred = true;
+ },
+ _onMouseDown: function(e){
+ if(e.cell == this){
+ this._startSelection(e.rowIndex);
+ evt.stop(e);
+ }
+ },
+ _onRowMouseOver: function(e){
+ // summary:
+ // Event fired when mouse moves over a data row(outside of this column).
+ // - from dojox.grid.enhanced._Events.onRowMouseOver()
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ this._updateSelection(e, 0);
+ },
+ _domouseup: function(e){
+ // summary:
+ // Event handler for mouse up event - from dojo.doc.domouseup()
+ // e: Event
+ // Mouse up event
+ if(has("ie")){
+ this.view.content.decorateEvent(e);//TODO - why only e in IE hasn't been decorated?
+ }
+ var inSwipeSelection = e.cellIndex >= 0 && this.inSwipeSelection() && !this.grid.edit.isEditRow(e.rowIndex);
+ if(inSwipeSelection){
+ this._focusEndingCell(e.rowIndex, e.cellIndex);
+ }
+ this._finishSelect();
+ },
+ _dokeyup: function(e){
+ // summary:
+ // Event handler for key up event
+ // - from dojox.grid.enhanced._Events.dokeyup()
+ // e: Event
+ // Key up event
+ this.inherited(arguments);
+ if(!e.shiftKey){
+ this._finishSelect();
+ }
+ },
+ _startSelection: function(rowIndex){
+ // summary:
+ // Initialize parameters to start a new swipe selection
+ // rowIndex: Integer
+ // Index of the start row
+ this.swipeStartRowIndex = this.swipeMinRowIndex = this.swipeMaxRowIndex = rowIndex;
+ this.toSelect = !this.getValue(rowIndex);
+ },
+ _updateSelection: function(e, delta){
+ // summary:
+ // Update row selections, fired during a swipe selection
+ // e: Event
+ // Event of the current row,
+ // delta: Integer
+ // Row index delta, used for swipe selection via Shift + Arrow key
+ // 0: not via key, -1 : Shift + Up, 1 : Shift + Down
+ if(!this.inSwipeSelection()){ return; }
+
+ var byKey = delta !== 0;//whether via Shift + Arrow Key
+ var currRow = e.rowIndex, deltaRow = currRow - this.swipeStartRowIndex + delta;
+ if(deltaRow > 0 && this.swipeMaxRowIndex < currRow + delta){
+ this.swipeMaxRowIndex = currRow + delta;
+ }
+ if(deltaRow < 0 && this.swipeMinRowIndex > currRow + delta){
+ this.swipeMinRowIndex = currRow + delta;
+ }
+
+ var min = deltaRow > 0 ? this.swipeStartRowIndex : currRow + delta;
+ var max = deltaRow > 0 ? currRow + delta : this.swipeStartRowIndex;
+ for(var i = this.swipeMinRowIndex; i <= this.swipeMaxRowIndex; i++){
+ if(this.disabledMap[i] || i < 0){ continue; }
+ if(i >= min && i <= max){//deltaRow != 0 || this.toSelect
+ this._nativeSelect(i, this.toSelect);
+ }else if(!byKey){
+ this._nativeSelect(i, !this.toSelect);
+ }
+ }
+ },
+ _swipeByKey: function(rowOffset, colOffset, e){
+ // summary:
+ // Update row selections, fired when Shift + Cursor is used for swipe selection
+ // See dojox.grid.enhanced._Events.onKeyDown
+ // e: Event
+ // Event of the current row,
+ // rowOffset: Integer
+ // Row offset, used for swipe selection via Shift + Cursor
+ // -1 : Shift + Up, 1 : Shift + Down
+ if(!e || rowOffset === 0 || !e.shiftKey || e.cellIndex != this.index ||
+ this.grid.focus.rowIndex < 0){ //TBD - e.rowIndex == 0 && delta == -1
+ return;
+ }
+ var rowIndex = e.rowIndex;
+ if(this.swipeStartRowIndex < 0){
+ //A new swipe selection starts via Shift + Arrow key
+ this.swipeStartRowIndex = rowIndex;
+ if(rowOffset > 0){//Shift + Down
+ this.swipeMaxRowIndex = rowIndex + rowOffset;
+ this.swipeMinRowIndex = rowIndex;
+ }else{//Shift + UP
+ this.swipeMinRowIndex = rowIndex + rowOffset;
+ this.swipeMaxRowIndex = rowIndex;
+ }
+ this.toSelect = this.getValue(rowIndex);
+ }
+ this._updateSelection(e, rowOffset);
+ },
+ _finishSelect: function(){
+ // summary:
+ // Reset parameters to end a swipe selection
+ this.swipeStartRowIndex = -1;
+ this.swipeMinRowIndex = -1;
+ this.swipeMaxRowIndex = -1;
+ this.toSelect = false;
+ },
+ inSwipeSelection: function(){
+ // summary:
+ // Check if during a swipe selection
+ // return: Boolean
+ // Whether in swipe selection
+ return this.swipeStartRowIndex >= 0;
+ },
+ _nativeSelect: function(index, value){
+ // summary:
+ // Overwritten
+ this.grid.selection[value ? 'addToSelection' : 'deselect'](index);
+ },
+ _selectRow: function(e){
+ // summary:
+ // Select the target row or range or rows
+ // e: Event
+ // Event fired on the target row
+ var rowIndex = e.rowIndex;
+ if(this.disabledMap[rowIndex]){ return; }
+ evt.stop(e);
+ this._focusEndingCell(rowIndex, 0);
+
+ var delta = rowIndex - this.lastClickRowIdx;
+ var newValue = !this.grid.selection.selected[rowIndex];
+ if(this.lastClickRowIdx >= 0 && !e.ctrlKey && !e.altKey && e.shiftKey){
+ var min = delta > 0 ? this.lastClickRowIdx : rowIndex;
+ var max = delta > 0 ? rowIndex : this.lastClickRowIdx;
+ for(var i = min; i >= 0 && i <= max; i++){
+ this._nativeSelect(i, newValue);
+ }
+ }else{
+ this._nativeSelect(rowIndex, newValue);
+ }
+ this.lastClickRowIdx = rowIndex;
+ },
+ getValue: function(rowIndex){
+ // summary:
+ // Overwritten
+ if(rowIndex == -1){//header selector
+ var g = this.grid;
+ return g.rowCount > 0 && g.rowCount <= g.selection.getSelectedCount();
+ }
+ return this.inherited(arguments);
+ },
+ _addHeaderSelector: function(){
+ // summary:
+ // Add selector in column header for selecting|deselecting all
+ var headerCellNode = this.view.getHeaderCellNode(this.index);
+ if(!headerCellNode){ return; }
+ html.empty(headerCellNode);
+ var g = this.grid;
+ var selector = headerCellNode.appendChild(html.create("div", {
+ 'aria-label': g._nls["selectAll"],
+ "tabindex": -1, "id": g.id + "_rowSelector_-1", "class": this.baseClass, "role": "presentation",
+ "innerHTML": "<span class = '" + this.statusTextClass +
+ "'></span><span style='height: 0; width: 0; overflow: hidden; display: block;'>" +
+ g._nls["selectAll"] + "</span>"
+ }));
+ this.map[-1] = selector;
+ var idx = this._headerSelectorConnectIdx;
+ if(idx !== undefined){
+ connect.disconnect(this._connects[idx]);
+ this._connects.splice(idx, 1);
+ }
+ this._headerSelectorConnectIdx = this._connects.length;
+ this._connects.push(connect.connect(selector, 'onclick', this, '_toggletHeader'));
+ this._onSelectionChanged();
+ },
+ _toggletHeader: function(){
+ // summary:
+ // Toggle state for head selector
+ if(!!this.disabledMap[-1]){ return; }
+ this.grid._selectingRange = true;
+ this.toggleAllSelection(!this.getValue(-1));
+ this._onSelectionChanged();
+ this.grid._selectingRange = false;
+ },
+ _onSelectionChanged: function(){
+ // summary:
+ // Update header selector anytime selection changed
+ var g = this.grid;
+ if(!this.map[-1] || g._selectingRange){ return; }
+ g.allItemsSelected = this.getValue(-1);
+ this._toggleCheckedStyle(-1, g.allItemsSelected);
+ },
+ _toggleDisabledStyle: function(index, disabled){
+ // summary:
+ // Overwritten
+ this.inherited(arguments);
+ if(this.headerSelector){
+ var allDisabled = (this.grid.rowCount == this.disabledCount);
+ if(allDisabled != !!this.disabledMap[-1]){//only if needed
+ arguments[0] = -1;
+ arguments[1] = allDisabled;
+ this.inherited(arguments);
+ }
+ }
+ }
+});
+
+var IndirectSelection = declare("dojox.grid.enhanced.plugins.IndirectSelection", _Plugin, {
+ // summary:
+ // A handy way for adding check boxe/radio button for rows, and selecting rows by swiping(or keyboard)
+
+ // description:
+ // For better rendering performance, div(images) are used to simulate radio button|check boxes
+ //
+ // example:
+ // <div dojoType="dojox.grid.EnhancedGrid" plugins="{indirectSelection: true}" ...></div>
+ // or <div dojoType="dojox.grid.EnhancedGrid" plugins="{indirectSelection: {name: 'xxx', width:'30px', styles:'text-align: center;'}}" ...></div>
+
+ //name: String
+ // Plugin name
+ name: "indirectSelection",
+
+ constructor: function(){
+ //Hook layout.setStructure(), so that indirectSelection is always included
+ var layout = this.grid.layout;
+ this.connect(layout, 'setStructure', lang.hitch(layout, this.addRowSelectCell, this.option));
+ },
+ addRowSelectCell: function(option){
+ // summary:
+ // Add indirectSelection cell(mapped to a column of radio button|check boxes)
+ if(!this.grid.indirectSelection || this.grid.selectionMode == 'none'){
+ return;
+ }
+ var rowSelectCellAdded = false, inValidFields = ['get', 'formatter', 'field', 'fields'],
+ defaultCellDef = {type: MultipleRowSelector, name: '', width:'30px', styles:'text-align: center;'};
+ if(option.headerSelector){ option.name = ''; }//mutual conflicting attrs
+
+ if(this.grid.rowSelectCell){//remove the existed one
+ this.grid.rowSelectCell.destroy();
+ }
+
+ array.forEach(this.structure, function(view){
+ var cells = view.cells;
+ if(cells && cells.length > 0 && !rowSelectCellAdded){
+ var firstRow = cells[0];
+ if(firstRow[0] && firstRow[0].isRowSelector){
+ console.debug('addRowSelectCell() - row selector cells already added, return.');
+ rowSelectCellAdded = true;
+ return;
+ }
+ var selectDef, cellType = this.grid.selectionMode == 'single' ? SingleRowSelector : MultipleRowSelector;
+ selectDef = lang.mixin(defaultCellDef, option, {type: cellType, editable: false, notselectable: true, filterable: false, navigatable: true, nosort: true});
+ array.forEach(inValidFields, function(field){//remove invalid fields
+ if(field in selectDef){ delete selectDef[field]; }
+ });
+ if(cells.length > 1){ selectDef.rowSpan = cells.length; }//for complicate layout
+ array.forEach(this.cells, function(cell, i){
+ if(cell.index >= 0){
+ cell.index += 1;
+ //console.debug('cell '+ (cell.index - 1) + ' is updated to index ' + cell.index);
+ }else{
+ console.warn('Error:IndirectSelection.addRowSelectCell()- cell ' + i + ' has no index!');
+ }
+ });
+ var rowSelectCell = this.addCellDef(0, 0, selectDef);
+ rowSelectCell.index = 0;
+ firstRow.unshift(rowSelectCell);
+ this.cells.unshift(rowSelectCell);
+ this.grid.rowSelectCell = rowSelectCell;
+ rowSelectCellAdded = true;
+ }
+ }, this);
+ this.cellCount = this.cells.length;
+ },
+ destroy: function(){
+ this.grid.rowSelectCell.destroy();
+ delete this.grid.rowSelectCell;
+ this.inherited(arguments);
+ }
+});
+
+EnhancedGrid.registerPlugin(IndirectSelection/*name:'indirectSelection'*/, {"preInit": true});
+
+return IndirectSelection;
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/Menu.js b/js/dojo/dojox/grid/enhanced/plugins/Menu.js
new file mode 100644
index 0000000..e65ac7b
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/Menu.js
@@ -0,0 +1,134 @@
+//>>built
+define("dojox/grid/enhanced/plugins/Menu", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/lang",
+ "dojo/_base/html",
+ "dojo/_base/event",
+ "dojo/keys",
+ "../_Plugin",
+ "../../EnhancedGrid"
+], function(declare, array, lang, html, evt, keys, _Plugin, EnhancedGrid){
+
+var Menu = declare("dojox.grid.enhanced.plugins.Menu", _Plugin, {
+ // summary:
+ // Provides context menu support, including header menu, row menu, cell menu and selected region menu
+ // example:
+ // <div dojoType="dojox.grid.EnhancedGrid"
+ // plugins="{menus:{headerMenu:"headerMenuId", rowMenu:"rowMenuId", cellMenu:"cellMenuId",
+ // selectedRegionMenu:"selectedRegionMenuId"}}" ...>
+ // </div>
+
+ //name: String
+ // Plugin name
+ name: "menus",
+
+ //name: [const] Array
+ // menu types
+ types: ['headerMenu', 'rowMenu', 'cellMenu', 'selectedRegionMenu'],
+
+ constructor: function(){
+ var g = this.grid;
+ g.showMenu = lang.hitch(g, this.showMenu);
+ g._setRowMenuAttr = lang.hitch(this, '_setRowMenuAttr');
+ g._setCellMenuAttr = lang.hitch(this, '_setCellMenuAttr');
+ g._setSelectedRegionMenuAttr = lang.hitch(this, '_setSelectedRegionMenuAttr');
+ },
+ onStartUp: function(){
+ var type, option = this.option;
+ for(type in option){
+ if(array.indexOf(this.types, type) >= 0 && option[type]){
+ this._initMenu(type, option[type]);
+ }
+ }
+ },
+ _initMenu: function(/*String*/menuType, /*String | Widget(dijit.Menu)*/menu){
+ var g = this.grid;
+ if(!g[menuType]){//in case already created in _Grid.postCreate()
+ var m = this._getMenuWidget(menu);
+ if(!m){return;}
+ g.set(menuType, m);
+ if(menuType != "headerMenu"){
+ m._scheduleOpen = function(){return;};
+ }else{
+ g.setupHeaderMenu();
+ }
+ }
+ },
+ _getMenuWidget: function(/*String|Widget(dijit.Menu)*/menu){
+ // summary:
+ // Fetch the required menu widget(should already been created)
+ return (menu instanceof dijit.Menu) ? menu : dijit.byId(menu);
+ },
+ _setRowMenuAttr: function(/*Widget(dijit.Menu)*/menu){
+ // summary:
+ // Set row menu widget
+ this._setMenuAttr(menu, 'rowMenu');
+ },
+ _setCellMenuAttr: function(/*Widget(dijit.Menu)*/menu){
+ // summary:
+ // Set cell menu widget
+ this._setMenuAttr(menu, 'cellMenu');
+ },
+ _setSelectedRegionMenuAttr: function(/*Widget(dijit.Menu)*/menu){
+ // summary:
+ // Set row menu widget
+ this._setMenuAttr(menu, 'selectedRegionMenu');
+ },
+ _setMenuAttr: function(/*Widget(dijit.Menu)*/menu, /*String*/menuType){
+ // summary:
+ // Bind menus to Grid.
+ var g = this.grid, n = g.domNode;
+ if(!menu || !(menu instanceof dijit.Menu)){
+ console.warn(menuType, " of Grid ", g.id, " is not existed!");
+ return;
+ }
+ if(g[menuType]){
+ g[menuType].unBindDomNode(n);
+ }
+ g[menuType] = menu;
+ g[menuType].bindDomNode(n);
+ },
+ showMenu: function(/*Event*/e){
+ // summary:
+ // Show appropriate context menu
+ // Fired from dojox.grid.enhanced._Events.onRowContextMenu, 'this' scope - Grid
+ // TODO: test Shift-F10
+ var inSelectedRegion = (e.cellNode && html.hasClass(e.cellNode, 'dojoxGridRowSelected') ||
+ e.rowNode && (html.hasClass(e.rowNode, 'dojoxGridRowSelected') || html.hasClass(e.rowNode, 'dojoxGridRowbarSelected')));
+
+ if(inSelectedRegion && this.selectedRegionMenu){
+ this.onSelectedRegionContextMenu(e);
+ return;
+ }
+
+ var info = {target: e.target, coords: e.keyCode !== keys.F10 && "pageX" in e ? {x: e.pageX, y: e.pageY } : null};
+ if(this.rowMenu && (!this.cellMenu || this.selection.isSelected(e.rowIndex) || e.rowNode && html.hasClass(e.rowNode, 'dojoxGridRowbar'))){
+ this.rowMenu._openMyself(info);
+ evt.stop(e);
+ return;
+ }
+
+ if(this.cellMenu){
+ this.cellMenu._openMyself(info);
+ }
+ evt.stop(e);
+ },
+ destroy: function(){
+ // summary:
+ // Destroy all resources.
+ // _Grid.destroy() will unbind headerMenu
+ var g = this.grid;
+ if(g.headerMenu){g.headerMenu.unBindDomNode(g.viewsHeaderNode);}
+ if(g.rowMenu){g.rowMenu.unBindDomNode(g.domNode);}
+ if(g.cellMenu){g.cellMenu.unBindDomNode(g.domNode);}
+ if(g.selectedRegionMenu){g.selectedRegionMenu.destroy();}
+ this.inherited(arguments);
+ }
+});
+
+EnhancedGrid.registerPlugin(Menu/*name:'menus'*/);
+
+return Menu;
+
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/NestedSorting.js b/js/dojo/dojox/grid/enhanced/plugins/NestedSorting.js
new file mode 100644
index 0000000..a27cddb
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/NestedSorting.js
@@ -0,0 +1,610 @@
+//>>built
+define("dojox/grid/enhanced/plugins/NestedSorting", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "dojo/_base/lang",
+ "dojo/_base/html",
+ "dojo/_base/event",
+ "dojo/_base/window",
+ "dojo/keys",
+ "dojo/query",
+ "dojo/string",
+ "../_Plugin",
+ "../../EnhancedGrid"
+], function(declare, array, connect, lang, html, evt, win, keys, query, string, _Plugin, EnhancedGrid){
+
+var NestedSorting = declare("dojox.grid.enhanced.plugins.NestedSorting", _Plugin, {
+ // summary:
+ // Provides nested sorting feature
+ //
+ // description:
+ // A flexible way to control multiple column sorting, including
+ // 1. Set default sorting order
+ // 2. Disable sorting for certain columns
+ // 3. Set sorting order dynamically with JS API
+ //
+ // example:
+ // | <script type="text/javascript">
+ // | var grid = new dojox.grid.EnhancedGrid({plugins : {nestedSorting: true}},
+ // | sortFields: [{attribute: 'col4', descending: false},...],//set default sorting order
+ // | canSort: function(index, field){ return true},//disable sorting for a column
+ // | ... }, dojo.byId('gridDiv'));
+ // | grid.startup();
+ // | //set new sorting order
+ // | grid.setSortIndex([{attribute: 'col3', descending: true},...])
+ // | </script>
+
+ // name: String
+ // Plugin name
+ name: "nestedSorting",
+
+ _currMainSort: 'none',//'none'|'asc'|'desc'
+
+ _currRegionIdx: -1,
+
+ _a11yText: {
+ 'dojoxGridDescending' : '&#9662;',
+ 'dojoxGridAscending' : '&#9652;',
+ 'dojoxGridAscendingTip' : '&#1784;',
+ 'dojoxGridDescendingTip': '&#1783;',
+ 'dojoxGridUnsortedTip' : 'x' //'&#10006;'
+ },
+
+ constructor: function(){
+ this._sortDef = [];
+ this._sortData = {};
+ this._headerNodes = {};
+ //column index that are hidden, un-sortable or indirect selection etc.
+ this._excludedColIdx = [];
+ this.nls = this.grid._nls;
+ this.grid.setSortInfo = function(){};
+ this.grid.setSortIndex = lang.hitch(this, '_setGridSortIndex');
+ this.grid.getSortIndex = function(){};
+ this.grid.getSortProps = lang.hitch(this, 'getSortProps');
+ if(this.grid.sortFields){
+ this._setGridSortIndex(this.grid.sortFields, null, true);
+ }
+ this.connect(this.grid.views, 'render', '_initSort');//including column resize
+ this.initCookieHandler();
+ this.subscribe("dojox/grid/rearrange/move/" + this.grid.id, lang.hitch(this, '_onColumnDnD'));
+ },
+ onStartUp: function(){
+ //overwrite base Grid functions
+ this.inherited(arguments);
+ this.connect(this.grid, 'onHeaderCellClick', '_onHeaderCellClick');
+ this.connect(this.grid, 'onHeaderCellMouseOver', '_onHeaderCellMouseOver');
+ this.connect(this.grid, 'onHeaderCellMouseOut', '_onHeaderCellMouseOut');
+ },
+ _onColumnDnD: function(type, mapping){
+ // summary:
+ // Update nested sorting after column moved
+ if(type !== 'col'){return;}
+ var m = mapping, obj = {}, d = this._sortData, p;
+ var cr = this._getCurrentRegion();
+ this._blurRegion(cr);
+ var idx = this._getRegionHeader(cr).getAttribute('idx');
+ for(p in m){
+ if(d[p]){
+ obj[m[p]] = d[p];
+ delete d[p];
+ }
+ if(p === idx){
+ idx = m[p];
+ }
+ }
+ for(p in obj){
+ d[p] = obj[p];
+ }
+ var c = this._headerNodes[idx];
+ this._currRegionIdx = array.indexOf(this._getRegions(), c.firstChild);
+ this._initSort(false);
+ },
+ _setGridSortIndex: function(inIndex, inAsc, noRefresh){
+ if(lang.isArray(inIndex)){
+ var i, d, cell;
+ for(i = 0; i < inIndex.length; i++){
+ d = inIndex[i];
+ cell = this.grid.getCellByField(d.attribute);
+ if(!cell){
+ console.warn('Invalid sorting option, column ', d.attribute, ' not found.');
+ return;
+ }
+ if(cell['nosort'] || !this.grid.canSort(cell.index, cell.field)){
+ console.warn('Invalid sorting option, column ', d.attribute, ' is unsortable.');
+ return;
+ }
+ }
+ this.clearSort();
+ array.forEach(inIndex, function(d, i){
+ cell = this.grid.getCellByField(d.attribute);
+ this.setSortData(cell.index, 'index', i);
+ this.setSortData(cell.index, 'order', d.descending ? 'desc': 'asc');
+ }, this);
+ }else if(!isNaN(inIndex)){
+ if(inAsc === undefined){ return; }//header click from base DataGrid
+ this.setSortData(inIndex, 'order', inAsc ? 'asc' : 'desc');
+ }else{
+ return;
+ }
+ this._updateSortDef();
+ if(!noRefresh){
+ this.grid.sort();
+ }
+ },
+ getSortProps: function(){
+ // summary:
+ // Overwritten, see DataGrid.getSortProps()
+ return this._sortDef.length ? this._sortDef : null;
+ },
+ _initSort: function(postSort){
+ // summary:
+ // Initiate sorting
+ var g = this.grid, n = g.domNode, len = this._sortDef.length;
+ html.toggleClass(n, 'dojoxGridSorted', !!len);
+ html.toggleClass(n, 'dojoxGridSingleSorted', len === 1);
+ html.toggleClass(n, 'dojoxGridNestSorted', len > 1);
+ if(len > 0){
+ this._currMainSort = this._sortDef[0].descending ? 'desc' : 'asc';
+ }
+ var idx, excluded = this._excludedCoIdx = [];//reset it
+ //cache column index of hidden, un-sortable or indirect selection
+ this._headerNodes = query("th", g.viewsHeaderNode).forEach(function(n){
+ idx = parseInt(n.getAttribute('idx'), 10);
+ if(html.style(n, 'display') === 'none' || g.layout.cells[idx]['nosort'] || (g.canSort && !g.canSort(idx, g.layout.cells[idx]['field']))){
+ excluded.push(idx);
+ }
+ });
+ this._headerNodes.forEach(this._initHeaderNode, this);
+ this._initFocus();
+ if(postSort){
+ this._focusHeader();
+ }
+ },
+ _initHeaderNode: function(node){
+ // summary:
+ // Initiate sort for each header cell node
+ html.toggleClass(node, 'dojoxGridSortNoWrap', true);
+ var sortNode = query('.dojoxGridSortNode', node)[0];
+ if(sortNode){
+ html.toggleClass(sortNode, 'dojoxGridSortNoWrap', true);
+ }
+ if(array.indexOf(this._excludedCoIdx, node.getAttribute('idx')) >= 0){
+ html.addClass(node, 'dojoxGridNoSort');
+ return;
+ }
+ if(!query('.dojoxGridSortBtn', node).length){
+ //clear any previous connects
+ this._connects = array.filter(this._connects, function(conn){
+ if(conn._sort){
+ connect.disconnect(conn);
+ return false;
+ }
+ return true;
+ });
+ var n = html.create('a', {
+ className: 'dojoxGridSortBtn dojoxGridSortBtnNested',
+ title: string.substitute(this.nls.sortingState, [this.nls.nestedSort, this.nls.ascending]),
+ innerHTML: '1'
+ }, node.firstChild, 'last');
+ n.onmousedown = evt.stop;
+ n = html.create('a', {
+ className: 'dojoxGridSortBtn dojoxGridSortBtnSingle',
+ title: string.substitute(this.nls.sortingState, [this.nls.singleSort, this.nls.ascending])
+ }, node.firstChild, 'last');
+ n.onmousedown = evt.stop;
+ }else{
+ //deal with small height grid which doesn't re-render the grid after refresh
+ var a1 = query('.dojoxGridSortBtnSingle', node)[0];
+ var a2 = query('.dojoxGridSortBtnNested', node)[0];
+ a1.className = 'dojoxGridSortBtn dojoxGridSortBtnSingle';
+ a2.className = 'dojoxGridSortBtn dojoxGridSortBtnNested';
+ a2.innerHTML = '1';
+ html.removeClass(node, 'dojoxGridCellShowIndex');
+ html.removeClass(node.firstChild, 'dojoxGridSortNodeSorted');
+ html.removeClass(node.firstChild, 'dojoxGridSortNodeAsc');
+ html.removeClass(node.firstChild, 'dojoxGridSortNodeDesc');
+ html.removeClass(node.firstChild, 'dojoxGridSortNodeMain');
+ html.removeClass(node.firstChild, 'dojoxGridSortNodeSub');
+ }
+ this._updateHeaderNodeUI(node);
+ },
+ _onHeaderCellClick: function(e){
+ // summary
+ // See dojox.grid.enhanced._Events._onHeaderCellClick()
+ this._focusRegion(e.target);
+ if(html.hasClass(e.target, 'dojoxGridSortBtn')){
+ this._onSortBtnClick(e);
+ evt.stop(e);
+ this._focusRegion(this._getCurrentRegion());
+ }
+ },
+ _onHeaderCellMouseOver: function(e){
+ // summary
+ // See dojox.grid._Events._onHeaderCellMouseOver()
+ // When user mouseover other columns than sorted column in a single sorted grid,
+ // We need to show 1 in the sorted column
+ if(!e.cell){return; }
+ if(this._sortDef.length > 1){ return; }
+ if(this._sortData[e.cellIndex] && this._sortData[e.cellIndex].index === 0){ return; }
+ var p;
+ for(p in this._sortData){
+ if(this._sortData[p] && this._sortData[p].index === 0){
+ html.addClass(this._headerNodes[p], 'dojoxGridCellShowIndex');
+ break;
+ }
+ }
+ if(!html.hasClass(win.body(), 'dijit_a11y')){ return; }
+ //a11y support
+ var i = e.cell.index, node = e.cellNode;
+ var singleSortBtn = query('.dojoxGridSortBtnSingle', node)[0];
+ var nestedSortBtn = query('.dojoxGridSortBtnNested', node)[0];
+
+ var sortMode = 'none';
+ if(html.hasClass(this.grid.domNode, 'dojoxGridSingleSorted')){
+ sortMode = 'single';
+ }else if(html.hasClass(this.grid.domNode, 'dojoxGridNestSorted')){
+ sortMode = 'nested';
+ }
+ var nestedIndex = nestedSortBtn.getAttribute('orderIndex');
+ if(nestedIndex === null || nestedIndex === undefined){
+ nestedSortBtn.setAttribute('orderIndex', nestedSortBtn.innerHTML);
+ nestedIndex = nestedSortBtn.innerHTML;
+ }
+ if(this.isAsc(i)){
+ nestedSortBtn.innerHTML = nestedIndex + this._a11yText.dojoxGridDescending;
+ }else if(this.isDesc(i)){
+ nestedSortBtn.innerHTML = nestedIndex + this._a11yText.dojoxGridUnsortedTip;
+ }else{
+ nestedSortBtn.innerHTML = nestedIndex + this._a11yText.dojoxGridAscending;
+ }
+ if(this._currMainSort === 'none'){
+ singleSortBtn.innerHTML = this._a11yText.dojoxGridAscending;
+ }else if(this._currMainSort === 'asc'){
+ singleSortBtn.innerHTML = this._a11yText.dojoxGridDescending;
+ }else if(this._currMainSort === 'desc'){
+ singleSortBtn.innerHTML = this._a11yText.dojoxGridUnsortedTip;
+ }
+ },
+ _onHeaderCellMouseOut: function(e){
+ // summary
+ // See dojox.grid.enhanced._Events._onHeaderCellMouseOut()
+ var p;
+ for(p in this._sortData){
+ if(this._sortData[p] && this._sortData[p].index === 0){
+ html.removeClass(this._headerNodes[p], 'dojoxGridCellShowIndex');
+ break;
+ }
+ }
+ },
+ _onSortBtnClick: function(e){
+ // summary:
+ // If the click target is single sort button, do single sort.
+ // Else if the click target is nested sort button, do nest sort.
+ // Otherwise return.
+ var cellIdx = e.cell.index;
+ if(html.hasClass(e.target, 'dojoxGridSortBtnSingle')){
+ this._prepareSingleSort(cellIdx);
+ }else if(html.hasClass(e.target, 'dojoxGridSortBtnNested')){
+ this._prepareNestedSort(cellIdx);
+ }else{
+ return;
+ }
+ evt.stop(e);
+ this._doSort(cellIdx);
+ },
+ _doSort: function(cellIdx){
+ if(!this._sortData[cellIdx] || !this._sortData[cellIdx].order){
+ this.setSortData(cellIdx, 'order', 'asc'); //no sorting data
+ }else if(this.isAsc(cellIdx)){
+ this.setSortData(cellIdx, 'order', 'desc'); //change to 'desc'
+ }else if(this.isDesc(cellIdx)){
+ this.removeSortData(cellIdx); //remove from sorting sequence
+ }
+ this._updateSortDef();
+ this.grid.sort();
+ this._initSort(true);
+ },
+ setSortData: function(cellIdx, attr, value){
+ // summary:
+ // Set sorting data for a column.
+ var sd = this._sortData[cellIdx];
+ if(!sd){
+ sd = this._sortData[cellIdx] = {};
+ }
+ sd[attr] = value;
+ },
+ removeSortData: function(cellIdx){
+ var d = this._sortData, i = d[cellIdx].index, p;
+ delete d[cellIdx];
+ for(p in d){
+ if(d[p].index > i){
+ d[p].index--;
+ }
+ }
+ },
+ _prepareSingleSort: function(cellIdx){
+ // summary:
+ // Prepare the single sort, also called main sort, this will clear any existing sorting and just sort the grid by current column.
+ var d = this._sortData, p;
+ for(p in d){
+ delete d[p];
+ }
+ this.setSortData(cellIdx, 'index', 0);
+ this.setSortData(cellIdx, 'order', this._currMainSort === 'none' ? null : this._currMainSort);
+ if(!this._sortData[cellIdx] || !this._sortData[cellIdx].order){
+ this._currMainSort = 'asc';
+ }else if(this.isAsc(cellIdx)){
+ this._currMainSort = 'desc';
+ }else if(this.isDesc(cellIdx)){
+ this._currMainSort = 'none';
+ }
+ },
+ _prepareNestedSort: function(cellIdx){
+ // summary
+ // Prepare the nested sorting, this will order the column on existing sorting result.
+ var i = this._sortData[cellIdx] ? this._sortData[cellIdx].index : null;
+ if(i === 0 || !!i){ return; }
+ this.setSortData(cellIdx, 'index', this._sortDef.length);
+ },
+ _updateSortDef: function(){
+ this._sortDef.length = 0;
+ var d = this._sortData, p;
+ for(p in d){
+ this._sortDef[d[p].index] = {
+ attribute: this.grid.layout.cells[p].field,
+ descending: d[p].order === 'desc'
+ };
+ }
+ },
+ _updateHeaderNodeUI: function(node){
+ // summary:
+ // Update the column header UI based on current sorting state.
+ // Show indicator of the sorting order of the column, no order no indicator
+ var cell = this._getCellByNode(node);
+ var cellIdx = cell.index;
+ var data = this._sortData[cellIdx];
+ var sortNode = query('.dojoxGridSortNode', node)[0];
+ var singleSortBtn = query('.dojoxGridSortBtnSingle', node)[0];
+ var nestedSortBtn = query('.dojoxGridSortBtnNested', node)[0];
+
+ html.toggleClass(singleSortBtn, 'dojoxGridSortBtnAsc', this._currMainSort === 'asc');
+ html.toggleClass(singleSortBtn, 'dojoxGridSortBtnDesc', this._currMainSort === 'desc');
+ if(this._currMainSort === 'asc'){
+ singleSortBtn.title = string.substitute(this.nls.sortingState, [this.nls.singleSort, this.nls.descending]);
+ }else if(this._currMainSort === 'desc'){
+ singleSortBtn.title = string.substitute(this.nls.sortingState, [this.nls.singleSort, this.nls.unsorted]);
+ }else{
+ singleSortBtn.title = string.substitute(this.nls.sortingState, [this.nls.singleSort, this.nls.ascending]);
+ }
+
+ var _this = this;
+ function setWaiState(){
+ var columnInfo = 'Column ' + (cell.index + 1) + ' ' + cell.field;
+ var orderState = 'none';
+ var orderAction = 'ascending';
+ if(data){
+ orderState = data.order === 'asc' ? 'ascending' : 'descending';
+ orderAction = data.order === 'asc' ? 'descending' : 'none';
+ }
+ var a11ySingleLabel = columnInfo + ' - is sorted by ' + orderState;
+ var a11yNestedLabel = columnInfo + ' - is nested sorted by ' + orderState;
+ var a11ySingleLabelHover = columnInfo + ' - choose to sort by ' + orderAction;
+ var a11yNestedLabelHover = columnInfo + ' - choose to nested sort by ' + orderAction;
+
+ singleSortBtn.setAttribute("aria-label", a11ySingleLabel);
+ nestedSortBtn.setAttribute("aria-label", a11yNestedLabel);
+
+ var handles = [
+ _this.connect(singleSortBtn, "onmouseover", function(){
+ singleSortBtn.setAttribute("aria-label", a11ySingleLabelHover);
+ }),
+ _this.connect(singleSortBtn, "onmouseout", function(){
+ singleSortBtn.setAttribute("aria-label", a11ySingleLabel);
+ }),
+ _this.connect(nestedSortBtn, "onmouseover", function(){
+ nestedSortBtn.setAttribute("aria-label", a11yNestedLabelHover);
+ }),
+ _this.connect(nestedSortBtn, "onmouseout", function(){
+ nestedSortBtn.setAttribute("aria-label", a11yNestedLabel);
+ })
+ ];
+ array.forEach(handles, function(handle){ handle._sort = true; });
+ }
+ setWaiState();
+
+ var a11y = html.hasClass(win.body(), "dijit_a11y");
+ if(!data){
+ nestedSortBtn.innerHTML = this._sortDef.length + 1;
+ nestedSortBtn.title = string.substitute(this.nls.sortingState, [this.nls.nestedSort, this.nls.ascending]);
+ if(a11y){sortNode.innerHTML = this._a11yText.dojoxGridUnsortedTip;}
+ return;
+ }
+ if(data.index || (data.index === 0 && this._sortDef.length > 1)){
+ nestedSortBtn.innerHTML = data.index + 1;
+ }
+ html.addClass(sortNode, 'dojoxGridSortNodeSorted');
+ if(this.isAsc(cellIdx)){
+ html.addClass(sortNode, 'dojoxGridSortNodeAsc');
+ nestedSortBtn.title = string.substitute(this.nls.sortingState, [this.nls.nestedSort, this.nls.descending]);
+ if(a11y){sortNode.innerHTML = this._a11yText.dojoxGridAscendingTip;}
+ }else if(this.isDesc(cellIdx)){
+ html.addClass(sortNode, 'dojoxGridSortNodeDesc');
+ nestedSortBtn.title = string.substitute(this.nls.sortingState, [this.nls.nestedSort, this.nls.unsorted]);
+ if(a11y){sortNode.innerHTML = this._a11yText.dojoxGridDescendingTip;}
+ }
+ html.addClass(sortNode, (data.index === 0 ? 'dojoxGridSortNodeMain' : 'dojoxGridSortNodeSub'));
+ },
+ isAsc: function(cellIndex){
+ return this._sortData[cellIndex].order === 'asc';
+ },
+ isDesc: function(cellIndex){
+ return this._sortData[cellIndex].order === 'desc';
+ },
+ _getCellByNode: function(node){
+ var i;
+ for(i = 0; i < this._headerNodes.length; i++){
+ if(this._headerNodes[i] === node){
+ return this.grid.layout.cells[i];
+ }
+ }
+ return null;
+ },
+ clearSort: function(){
+ this._sortData = {};
+ this._sortDef.length = 0;
+ },
+
+ //persistence
+ initCookieHandler: function(){
+ if(this.grid.addCookieHandler){
+ this.grid.addCookieHandler({
+ name: "sortOrder",
+ onLoad: lang.hitch(this, '_loadNestedSortingProps'),
+ onSave: lang.hitch(this, '_saveNestedSortingProps')
+ });
+ }
+ },
+ _loadNestedSortingProps: function(sortInfo, grid){
+ this._setGridSortIndex(sortInfo);
+ },
+ _saveNestedSortingProps: function(grid){
+ return this.getSortProps();
+ },
+
+ //focus & keyboard
+ _initFocus: function(){
+ var f = this.focus = this.grid.focus;
+ this._focusRegions = this._getRegions();
+ if(!this._headerArea){
+ var area = this._headerArea = f.getArea('header');
+ area.onFocus = f.focusHeader = lang.hitch(this, '_focusHeader');
+ area.onBlur = f.blurHeader = f._blurHeader = lang.hitch(this, '_blurHeader');
+ area.onMove = lang.hitch(this, '_onMove');
+ area.onKeyDown = lang.hitch(this, '_onKeyDown');
+ area._regions = [];
+ area.getRegions = null;
+ this.connect(this.grid, 'onBlur', '_blurHeader');
+ }
+ },
+ _focusHeader: function(e){
+ // summary:
+ // Overwritten, see _FocusManager.focusHeader()
+ //delayed: Boolean
+ // If called from "this.focus._delayedHeaderFocus()"
+ if(this._currRegionIdx === -1){
+ this._onMove(0, 1, null);
+ }else{
+ this._focusRegion(this._getCurrentRegion());
+ }
+ try{
+ evt.stop(e);
+ }catch(e){}
+ return true;
+ },
+ _blurHeader: function(e){
+ this._blurRegion(this._getCurrentRegion());
+ return true;
+ },
+ _onMove: function(rowStep, colStep, e){
+ var curr = this._currRegionIdx || 0, regions = this._focusRegions;
+ var region = regions[curr + colStep];
+ if(!region){
+ return;
+ }else if(html.style(region, 'display') === 'none' || html.style(region, 'visibility') === 'hidden'){
+ //if the region is invisible, keep finding next
+ this._onMove(rowStep, colStep + (colStep > 0 ? 1 : -1), e);
+ return;
+ }
+ this._focusRegion(region);
+ //keep grid body scrolled by header
+ var view = this._getRegionView(region);
+ view.scrollboxNode.scrollLeft = view.headerNode.scrollLeft;
+ },
+ _onKeyDown: function(e, isBubble){
+ if(isBubble){
+ switch(e.keyCode){
+ case keys.ENTER:
+ case keys.SPACE:
+ if(html.hasClass(e.target, 'dojoxGridSortBtnSingle') ||
+ html.hasClass(e.target, 'dojoxGridSortBtnNested')){
+ this._onSortBtnClick(e);
+ }
+ }
+ }
+ },
+ _getRegionView: function(region){
+ var header = region;
+ while(header && !html.hasClass(header, 'dojoxGridHeader')){ header = header.parentNode; }
+ if(header){
+ return array.filter(this.grid.views.views, function(view){
+ return view.headerNode === header;
+ })[0] || null;
+ }
+ return null;
+ },
+ _getRegions: function(){
+ var regions = [], cells = this.grid.layout.cells;
+ this._headerNodes.forEach(function(n, i){
+ if(html.style(n, 'display') === 'none'){return;}
+ if(cells[i]['isRowSelector']){
+ regions.push(n);
+ return;
+ }
+ query('.dojoxGridSortNode,.dojoxGridSortBtnNested,.dojoxGridSortBtnSingle', n).forEach(function(node){
+ node.setAttribute('tabindex', 0);
+ regions.push(node);
+ });
+ },this);
+ return regions;
+ },
+ _focusRegion: function(region){
+ // summary
+ // Focus the given region
+ if(!region){return;}
+ var currRegion = this._getCurrentRegion();
+ if(currRegion && region !== currRegion){
+ this._blurRegion(currRegion);
+ }
+ var header = this._getRegionHeader(region);
+ html.addClass(header, 'dojoxGridCellSortFocus');
+ if(html.hasClass(region, 'dojoxGridSortNode')){
+ html.addClass(region, 'dojoxGridSortNodeFocus');
+ }else if(html.hasClass(region, 'dojoxGridSortBtn')){
+ html.addClass(region, 'dojoxGridSortBtnFocus');
+ }
+ region.focus();
+ this.focus.currentArea('header');
+ this._currRegionIdx = array.indexOf(this._focusRegions, region);
+ },
+ _blurRegion: function(region){
+ if(!region){return;}
+ var header = this._getRegionHeader(region);
+ html.removeClass(header, 'dojoxGridCellSortFocus');
+ if(html.hasClass(region, 'dojoxGridSortNode')){
+ html.removeClass(region, 'dojoxGridSortNodeFocus');
+ }else if(html.hasClass(region, 'dojoxGridSortBtn')){
+ html.removeClass(region, 'dojoxGridSortBtnFocus');
+ }
+ region.blur();
+ },
+ _getCurrentRegion: function(){
+ return this._focusRegions ? this._focusRegions[this._currRegionIdx] : null;
+ },
+ _getRegionHeader: function(region){
+ while(region && !html.hasClass(region, 'dojoxGridCell')){
+ region = region.parentNode;
+ }
+ return region;
+ },
+ destroy: function(){
+ this._sortDef = this._sortData = null;
+ this._headerNodes = this._focusRegions = null;
+ this.inherited(arguments);
+ }
+});
+
+EnhancedGrid.registerPlugin(NestedSorting);
+
+return NestedSorting;
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/Pagination.js b/js/dojo/dojox/grid/enhanced/plugins/Pagination.js
new file mode 100644
index 0000000..244d79d
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/Pagination.js
@@ -0,0 +1,974 @@
+//>>built
+require({cache:{
+'url:dojox/grid/enhanced/templates/Pagination.html':"<div dojoAttachPoint=\"paginatorBar\"\n\t><table cellpadding=\"0\" cellspacing=\"0\" class=\"dojoxGridPaginator\"\n\t\t><tr\n\t\t\t><td dojoAttachPoint=\"descriptionTd\" class=\"dojoxGridDescriptionTd\"\n\t\t\t\t><div dojoAttachPoint=\"descriptionDiv\" class=\"dojoxGridDescription\"></div\n\t\t\t></div></td\n\t\t\t><td dojoAttachPoint=\"sizeSwitchTd\"></td\n\t\t\t><td dojoAttachPoint=\"pageStepperTd\" class=\"dojoxGridPaginatorFastStep\"\n\t\t\t\t><div dojoAttachPoint=\"pageStepperDiv\" class=\"dojoxGridPaginatorStep\"></div\n\t\t\t></td\n\t\t\t><td dojoAttachPoint=\"gotoPageTd\" class=\"dojoxGridPaginatorGotoTd\"\n\t\t\t\t><div dojoAttachPoint=\"gotoPageDiv\" class=\"dojoxGridPaginatorGotoDiv\" dojoAttachEvent=\"onclick:_openGotopageDialog, onkeydown:_openGotopageDialog\"\n\t\t\t\t\t><span class=\"dojoxGridWardButtonInner\">&#8869;</span\n\t\t\t\t></div\n\t\t\t></td\n\t\t></tr\n\t></table\n></div>\n"}});
+define("dojox/grid/enhanced/plugins/Pagination", [
+ "dojo/_base/kernel",
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "dojo/_base/lang",
+ "dojo/_base/html",
+ "dojo/_base/event",
+ "dojo/_base/window",
+ "dojo/query",
+ "dojo/string",
+ "dojo/i18n",
+ "dojo/keys",
+ "dojo/text!../templates/Pagination.html",
+ "./Dialog",
+ "./_StoreLayer",
+ "../_Plugin",
+ "../../EnhancedGrid",
+ "dijit/form/Button",
+ "dijit/form/NumberTextBox",
+ "dijit/focus",
+ "dijit/_Widget",
+ "dijit/_TemplatedMixin",
+ "dijit/_WidgetsInTemplateMixin",
+ "dojox/html/metrics",
+ "dojo/i18n!../nls/Pagination"
+], function(kernel, declare, array, connect, lang, html, event, win, query,
+ string, i18n, keys, template, Dialog, layers, _Plugin, EnhancedGrid,
+ Button, NumberTextBox, dijitFocus, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, metrics){
+
+var _GotoPagePane = declare("dojox.grid.enhanced.plugins.pagination._GotoPagePane", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin], {
+ templateString: "<div>" +
+ "<div class='dojoxGridDialogMargin' dojoAttachPoint='_mainMsgNode'></div>" +
+ "<div class='dojoxGridDialogMargin'>" +
+ "<input dojoType='dijit.form.NumberTextBox' style='width: 50px;' dojoAttachPoint='_pageInputBox' dojoAttachEvent='onKeyUp: _onKey'></input>" +
+ "<label dojoAttachPoint='_pageLabelNode'></label>" +
+ "</div>" +
+ "<div class='dojoxGridDialogButton'>" +
+ "<button dojoType='dijit.form.Button' dojoAttachPoint='_confirmBtn' dojoAttachEvent='onClick: _onConfirm'></button>" +
+ "<button dojoType='dijit.form.Button' dojoAttachPoint='_cancelBtn' dojoAttachEvent='onClick: _onCancel'></button>" +
+ "</div>" +
+ "</div>",
+ widgetsInTemplate: true,
+ dlg: null,
+ postMixInProperties: function(){
+ this.plugin = this.dlg.plugin;
+ },
+ postCreate: function(){
+ this.inherited(arguments);
+ this._mainMsgNode.innerHTML = this.plugin._nls[12];
+ this._confirmBtn.set("label", this.plugin._nls[14]);
+ this._confirmBtn.set("disabled", true);
+ this._cancelBtn.set("label", this.plugin._nls[15]);
+ },
+ _onConfirm: function(evt){
+ if(this._pageInputBox.isValid() && this._pageInputBox.getDisplayedValue() !== ""){
+ this.plugin.currentPage(this._pageInputBox.parse(this._pageInputBox.getDisplayedValue()));
+ this.dlg._gotoPageDialog.hide();
+ this._pageInputBox.reset();
+ }
+ stopEvent(evt);
+ },
+ _onCancel: function(evt){
+ this._pageInputBox.reset();
+ this.dlg._gotoPageDialog.hide();
+ stopEvent(evt);
+ },
+ _onKey: function(evt){
+ this._confirmBtn.set("disabled", !this._pageInputBox.isValid() || this._pageInputBox.getDisplayedValue() == "");
+ if(!evt.altKey && !evt.metaKey && evt.keyCode === keys.ENTER){
+ this._onConfirm(evt);
+ }
+ }
+});
+
+var _GotoPageDialog = declare("dojox.grid.enhanced.plugins.pagination._GotoPageDialog", null, {
+ pageCount: 0,
+ dlgPane: null,
+ constructor: function(plugin){
+ this.plugin = plugin;
+ this.dlgPane = new _GotoPagePane({"dlg": this});
+ this.dlgPane.startup();
+ this._gotoPageDialog = new Dialog({
+ "refNode": plugin.grid.domNode,
+ "title": this.plugin._nls[11],
+ "content": this.dlgPane
+ });
+ this._gotoPageDialog.startup();
+ },
+ _updatePageCount: function(){
+ this.pageCount = this.plugin.getTotalPageNum();
+ this.dlgPane._pageInputBox.constraints = {fractional:false, min:1, max:this.pageCount};
+ this.dlgPane._pageLabelNode.innerHTML = string.substitute(this.plugin._nls[13], [this.pageCount]);
+ },
+ showDialog: function(){
+ this._updatePageCount();
+ this._gotoPageDialog.show();
+ },
+ destroy: function(){
+ this._gotoPageDialog.destroy();
+ }
+});
+
+var _ForcedPageStoreLayer = declare("dojox.grid.enhanced.plugins._ForcedPageStoreLayer", layers._StoreLayer, {
+ tags: ["presentation"],
+ constructor: function(plugin){
+ this._plugin = plugin;
+ },
+ _fetch: function(request){
+ var _this = this,
+ plugin = _this._plugin,
+ grid = plugin.grid,
+ scope = request.scope || win.global,
+ onBegin = request.onBegin;
+ request.start = (plugin._currentPage - 1) * plugin._currentPageSize + request.start;
+ _this.startIdx = request.start;
+ _this.endIdx = request.start + plugin._currentPageSize - 1;
+ var p = plugin._paginator;
+ if(!plugin._showAll){
+ plugin._showAll = !p.sizeSwitch && !p.pageStepper && !p.gotoButton;
+ }
+ if(onBegin && plugin._showAll){
+ request.onBegin = function(size, req){
+ plugin._maxSize = plugin._currentPageSize = size;
+ _this.startIdx = 0;
+ _this.endIdx = size - 1;
+ plugin._paginator._update();
+ req.onBegin = onBegin;
+ req.onBegin.call(scope, size, req);
+ };
+ }else if(onBegin){
+ request.onBegin = function(size, req){
+ req.start = 0;
+ req.count = plugin._currentPageSize;
+ plugin._maxSize = size;
+ _this.endIdx = _this.endIdx >= size ? (size - 1) : _this.endIdx;
+ if(_this.startIdx > size && size !== 0){
+ grid._pending_requests[req.start] = false;
+ plugin.firstPage();
+ }
+ plugin._paginator._update();
+ req.onBegin = onBegin;
+ req.onBegin.call(scope, Math.min(plugin._currentPageSize, (size - _this.startIdx)), req);
+ };
+ }
+ return lang.hitch(this._store, this._originFetch)(request);
+ }
+});
+
+var stopEvent = function(evt){
+ try{
+ event.stop(evt);
+ }catch(e){}
+};
+
+var _Focus = declare("dojox.grid.enhanced.plugins.pagination._Focus", null, {
+ _focusedNode: null,
+ _isFocused: false,
+ constructor: function(paginator){
+ this._pager = paginator;
+ var focusMgr = paginator.plugin.grid.focus;
+ paginator.plugin.connect(paginator, 'onSwitchPageSize', lang.hitch(this, '_onActive'));
+ paginator.plugin.connect(paginator, 'onPageStep', lang.hitch(this, '_onActive'));
+ paginator.plugin.connect(paginator, 'onShowGotoPageDialog', lang.hitch(this, '_onActive'));
+ paginator.plugin.connect(paginator, '_update', lang.hitch(this, '_moveFocus'));
+ },
+ _onFocus: function(evt, step){
+ var node, nodes;
+ if(!this._isFocused){
+ node = this._focusedNode || query('[tabindex]', this._pager.domNode)[0];
+ }else if(step && this._focusedNode){
+ var dir = step > 0 ? -1 : 1,
+ tabindex = parseInt(this._focusedNode.getAttribute('tabindex'), 10) + dir;
+ while(tabindex >= -3 && tabindex < 0){
+ node = query('[tabindex=' + tabindex + ']', this._pager.domNode)[0];
+ if(node){
+ break;
+ }else{
+ tabindex += dir;
+ }
+ }
+ }
+ return this._focus(node, evt);
+ },
+ _onBlur: function(evt, step){
+ if(!step || !this._focusedNode){
+ this._isFocused = false;
+ if(this._focusedNode && html.hasClass(this._focusedNode, 'dojoxGridButtonFocus')){
+ html.removeClass(this._focusedNode, 'dojoxGridButtonFocus');
+ }
+ return true;
+ }
+ var node, dir = step > 0 ? -1 : 1,
+ tabindex = parseInt(this._focusedNode.getAttribute('tabindex'), 10) + dir;
+ while(tabindex >= -3 && tabindex < 0){
+ node = query('[tabindex=' + tabindex + ']', this._pager.domNode)[0];
+ if(node){
+ break;
+ }else{
+ tabindex += dir;
+ }
+ }
+ if(!node){
+ this._isFocused = false;
+ if(html.hasClass(this._focusedNode, 'dojoxGridButtonFocus')){
+ html.removeClass(this._focusedNode, 'dojoxGridButtonFocus');
+ }
+ }
+ return node ? false : true;
+ },
+ _onMove: function(rowDelta, colDelta, evt){
+ if(this._focusedNode){
+ var tabindex = this._focusedNode.getAttribute('tabindex'),
+ delta = colDelta == 1 ? "nextSibling" : "previousSibling",
+ node = this._focusedNode[delta];
+ while(node){
+ if(node.getAttribute('tabindex') == tabindex){
+ this._focus(node);
+ break;
+ }
+ node = node[delta];
+ }
+ }
+ },
+ _focus: function(node, evt){
+ if(node){
+ this._isFocused = true;
+ if(kernel.isIE && this._focusedNode){
+ html.removeClass(this._focusedNode, 'dojoxGridButtonFocus');
+ }
+ this._focusedNode = node;
+ node.focus();
+ if(kernel.isIE){
+ html.addClass(node, 'dojoxGridButtonFocus');
+ }
+ stopEvent(evt);
+ return true;
+ }
+ return false;
+ },
+ _onActive: function(e){
+ this._focusedNode = e.target;
+ if(!this._isFocused){
+ this._pager.plugin.grid.focus.focusArea('pagination' + this._pager.position);
+ }
+ },
+ _moveFocus: function(){
+ if(this._focusedNode && !this._focusedNode.getAttribute('tabindex')){
+ var next = this._focusedNode.nextSibling;
+ while(next){
+ if(next.getAttribute('tabindex')){
+ this._focus(next);
+ return;
+ }
+ next = next.nextSibling;
+ }
+ var prev = this._focusedNode.previousSibling;
+ while(prev){
+ if(prev.getAttribute('tabindex')){
+ this._focus(prev);
+ return;
+ }
+ prev = prev.previousSibling;
+ }
+ this._focusedNode = null;
+ this._onBlur();
+ }else if(kernel.isIE && this._focusedNode){
+ html.addClass(this._focusedNode, 'dojoxGridButtonFocus');
+ }
+ }
+});
+
+var _Paginator = declare("dojox.grid.enhanced.plugins._Paginator", [_Widget, _TemplatedMixin], {
+ templateString: template,
+ constructor: function(params){
+ lang.mixin(this, params);
+ this.grid = this.plugin.grid;
+ },
+ postCreate: function(){
+ this.inherited(arguments);
+ var _this = this, g = this.grid;
+ this.plugin.connect(g, "_resize", lang.hitch(this, "_resetGridHeight"));
+ this._originalResize = g.resize;
+ g.resize = function(changeSize, resultSize){
+ _this._changeSize = changeSize;
+ _this._resultSize = resultSize;
+ _this._originalResize.apply(g, arguments);
+ };
+ this.focus = _Focus(this);
+ this._placeSelf();
+ },
+ destroy: function(){
+ this.inherited(arguments);
+ this.grid.focus.removeArea("pagination" + this.position);
+ if(this._gotoPageDialog){
+ this._gotoPageDialog.destroy();
+ }
+ this.grid.resize = this._originalResize;
+ },
+ onSwitchPageSize: function(/*Event*/evt){
+
+ },
+ onPageStep: function(/*Event*/evt){
+
+ },
+ onShowGotoPageDialog: function(/*Event*/evt){
+
+ },
+ _update: function(){
+ // summary:
+ // Function to update paging information and update
+ // pagination bar display.
+ this._updateDescription();
+ this._updatePageStepper();
+ this._updateSizeSwitch();
+ this._updateGotoButton();
+ },
+ _registerFocus: function(isTop){
+ // summary:
+ // Function to register pagination bar to focus manager.
+ var focusMgr = this.grid.focus,
+ name = "pagination" + this.position,
+ f = this.focus;
+ focusMgr.addArea({
+ name: name,
+ onFocus: lang.hitch(this.focus, "_onFocus"),
+ onBlur: lang.hitch(this.focus, "_onBlur"),
+ onMove: lang.hitch(this.focus, "_onMove")
+ });
+ focusMgr.placeArea(name, isTop ? "before" : "after", isTop ? "header" : "content");
+ },
+ _placeSelf: function(){
+ // summary:
+ // Place pagination bar to a position.
+ // There are two options, top of the grid, bottom of the grid.
+ var g = this.grid,
+ isTop = this.position == "top";
+ this.placeAt(isTop ? g.viewsHeaderNode : g.viewsNode, isTop ? "before" : "after");
+ this._registerFocus(isTop);
+ },
+ _resetGridHeight: function(changeSize, resultSize){
+ // summary:
+ // Function of resize grid height to place this pagination bar.
+ // Since the grid would be able to add other element in its domNode, we have
+ // change the grid view size to place the pagination bar.
+ // This function will resize the grid viewsNode height, scorllboxNode height
+ var g = this.grid;
+ changeSize = changeSize || this._changeSize;
+ resultSize = resultSize || this._resultSize;
+ delete this._changeSize;
+ delete this._resultSize;
+ if(g._autoHeight){
+ return;
+ }
+ var padBorder = g._getPadBorder().h;
+ if(!this.plugin.gh){
+ this.plugin.gh = html.contentBox(g.domNode).h + 2 * padBorder;
+ }
+ if(resultSize){
+ changeSize = resultSize;
+ }
+ if(changeSize){
+ this.plugin.gh = html.contentBox(g.domNode).h + 2 * padBorder;
+ }
+ var gh = this.plugin.gh,
+ hh = g._getHeaderHeight(),
+ ph = html.marginBox(this.domNode).h;
+ // ph = this.plugin._paginator.position == "bottom" ? ph * 2 : ph;
+ if(typeof g.autoHeight === "number"){
+ var cgh = gh + ph - padBorder;
+ html.style(g.domNode, "height", cgh + "px");
+ html.style(g.viewsNode, "height", (cgh - ph - hh) + "px");
+ this._styleMsgNode(hh, html.marginBox(g.viewsNode).w, cgh - ph - hh);
+ }else{
+ var h = gh - ph - hh - padBorder;
+ html.style(g.viewsNode, "height", h + "px");
+ var hasHScroller = array.some(g.views.views, function(v){
+ return v.hasHScrollbar();
+ });
+ array.forEach(g.viewsNode.childNodes, function(c){
+ html.style(c, "height", h + "px");
+ });
+ array.forEach(g.views.views, function(v){
+ if(v.scrollboxNode){
+ if(!v.hasHScrollbar() && hasHScroller){
+ html.style(v.scrollboxNode, "height", (h - metrics.getScrollbar().h) + "px");
+ }else{
+ html.style(v.scrollboxNode, "height", h + "px");
+ }
+ }
+ });
+ this._styleMsgNode(hh, html.marginBox(g.viewsNode).w, h);
+ }
+ },
+ _styleMsgNode: function(top, width, height){
+ var messagesNode = this.grid.messagesNode;
+ html.style(messagesNode, {"position": "absolute", "top": top + "px", "width": width + "px", "height": height + "px", "z-Index": "100"});
+ },
+ _updateDescription: function(){
+ // summary:
+ // Update size information.
+ var s = this.plugin.forcePageStoreLayer,
+ maxSize = this.plugin._maxSize,
+ nls = this.plugin._nls,
+ getItemTitle = function(){
+ return maxSize <= 0 || maxSize == 1 ? nls[5] : nls[4];
+ };
+ if(this.description && this.descriptionDiv){
+ this.descriptionDiv.innerHTML = maxSize > 0 ? string.substitute(nls[0], [getItemTitle(), maxSize, s.startIdx + 1, s.endIdx + 1]) : "0 " + getItemTitle();
+ }
+ },
+ _updateSizeSwitch: function(){
+ // summary:
+ // Update "items per page" information.
+ html.style(this.sizeSwitchTd, "display", this.sizeSwitch ? "" : "none");
+ if(!this.sizeSwitch){
+ return;
+ }
+ if(this.sizeSwitchTd.childNodes.length < 1){
+ this._createSizeSwitchNodes();
+ }
+ this._updateSwitchNodesStyle();
+ },
+ _createSizeSwitchNodes: function(){
+ // summary:
+ // The function to create the size switch nodes
+ var node = null,
+ nls = this.plugin._nls,
+ connect = lang.hitch(this.plugin, 'connect');
+ array.forEach(this.pageSizes, function(size){
+ // create page size switch node
+ var labelValue = isFinite(size) ? string.substitute(nls[2], [size]) : nls[1],
+ value = isFinite(size) ? size : nls[16];
+ node = html.create("span", {innerHTML: value, title: labelValue, value: size, tabindex: "-1"}, this.sizeSwitchTd, "last");
+ // for accessibility
+ node.setAttribute("aria-label", labelValue);
+ // connect event
+ connect(node, "onclick", lang.hitch(this, "_onSwitchPageSize"));
+ connect(node, "onkeydown", lang.hitch(this, "_onSwitchPageSize"));
+ connect(node, "onmouseover", function(e){
+ html.addClass(e.target, "dojoxGridPageTextHover");
+ });
+ connect(node, "onmouseout", function(e){
+ html.removeClass(e.target, "dojoxGridPageTextHover");
+ });
+ // create a separation node
+ node = html.create("span", {innerHTML: "|"}, this.sizeSwitchTd, "last");
+ html.addClass(node, "dojoxGridSeparator");
+ }, this);
+ // delete last separation node
+ html.destroy(node);
+ },
+ _updateSwitchNodesStyle: function(){
+ // summary:
+ // Update the switch nodes style
+ var size = null;
+ var styleNode = function(node, status){
+ if(status){
+ html.addClass(node, "dojoxGridActivedSwitch");
+ html.removeAttr(node, "tabindex");
+ }else{
+ html.addClass(node, "dojoxGridInactiveSwitch");
+ node.setAttribute("tabindex", "-1");
+ }
+ };
+ array.forEach(this.sizeSwitchTd.childNodes, function(node){
+ if(node.value){
+ html.removeClass(node);
+ size = node.value;
+ if(this.plugin._showAll){
+ styleNode(node, isNaN(parseInt(size, 10)));
+ }else{
+ styleNode(node, this.plugin._currentPageSize == size);
+ }
+ }
+ }, this);
+ },
+ _updatePageStepper: function(){
+ // summary:
+ // Update the page step nodes
+ html.style(this.pageStepperTd, "display", this.pageStepper ? "" : "none");
+ if(!this.pageStepper){
+ return;
+ }
+ if(this.pageStepperDiv.childNodes.length < 1){
+ this._createPageStepNodes();
+ this._createWardBtns();
+ }else{
+ this._resetPageStepNodes();
+ }
+ this._updatePageStepNodesStyle();
+ },
+ _createPageStepNodes: function(){
+ // summary:
+ // Create the page step nodes if they do not exist
+ var startPage = this._getStartPage(),
+ stepSize = this._getStepPageSize(),
+ label = "", node = null, i = startPage,
+ connect = lang.hitch(this.plugin, 'connect');
+ for(; i < startPage + this.maxPageStep + 1; i++){
+ label = string.substitute(this.plugin._nls[3], [i]);
+ node = html.create("div", {innerHTML: i, value: i, title: label}, this.pageStepperDiv, "last");
+ node.setAttribute("aria-label", label);
+ // connect event
+ connect(node, "onclick", lang.hitch(this, "_onPageStep"));
+ connect(node, "onkeydown", lang.hitch(this, "_onPageStep"));
+ connect(node, "onmouseover", function(e){
+ html.addClass(e.target, "dojoxGridPageTextHover");
+ });
+ connect(node, "onmouseout", function(e){
+ html.removeClass(e.target, "dojoxGridPageTextHover");
+ });
+ html.style(node, "display", i < startPage + stepSize ? "" : "none");
+ }
+ },
+ _createWardBtns: function(){
+ // summary:
+ // Create the previous/next/first/last button
+ var _this = this, nls = this.plugin._nls;
+ var highContrastLabel = {prevPage: "&#60;", firstPage: "&#171;", nextPage: "&#62;", lastPage: "&#187;"};
+ var createWardBtn = function(value, label, position){
+ var node = html.create("div", {value: value, title: label, tabindex: "-2"}, _this.pageStepperDiv, position);
+ _this.plugin.connect(node, "onclick", lang.hitch(_this, "_onPageStep"));
+ _this.plugin.connect(node, "onkeydown", lang.hitch(_this, "_onPageStep"));
+ node.setAttribute("aria-label", label);
+ // for high contrast
+ var highConrastNode = html.create("span", {value: value, title: label, innerHTML: highContrastLabel[value]}, node, position);
+ html.addClass(highConrastNode, "dojoxGridWardButtonInner");
+ };
+ createWardBtn("prevPage", nls[6], "first");
+ createWardBtn("firstPage", nls[7], "first");
+ createWardBtn("nextPage", nls[8], "last");
+ createWardBtn("lastPage", nls[9], "last");
+ },
+ _resetPageStepNodes: function(){
+ // summary:
+ // The page step nodes might be changed when fetch data, we need to
+ // update/reset them
+ var startPage = this._getStartPage(),
+ stepSize = this._getStepPageSize(),
+ stepNodes = this.pageStepperDiv.childNodes,
+ node = null, i = startPage, j = 2, tip;
+ for(; j < stepNodes.length - 2; j++, i++){
+ node = stepNodes[j];
+ if(i < startPage + stepSize){
+ tip = string.substitute(this.plugin._nls[3], [i]);
+ html.attr(node, {
+ "innerHTML": i,
+ "title": tip,
+ "value": i
+ });
+ html.style(node, "display", "");
+ node.setAttribute("aria-label", tip);
+ }else{
+ html.style(node, "display", "none");
+ }
+ }
+ },
+ _updatePageStepNodesStyle: function(){
+ // summary:
+ // Update the style of the page step nodes
+ var value = null,
+ curPage = this.plugin.currentPage(),
+ pageCount = this.plugin.getTotalPageNum();
+ var updateClass = function(node, isWardBtn, status){
+ var value = node.value,
+ enableClass = isWardBtn ? "dojoxGrid" + value + "Btn" : "dojoxGridInactived",
+ disableClass = isWardBtn ? "dojoxGrid" + value + "BtnDisable" : "dojoxGridActived";
+ if(status){
+ html.addClass(node, disableClass);
+ html.removeAttr(node, "tabindex");
+ }else{
+ html.addClass(node, enableClass);
+ node.setAttribute("tabindex", "-2");
+ }
+ };
+ array.forEach(this.pageStepperDiv.childNodes, function(node){
+ html.removeClass(node);
+ if(isNaN(parseInt(node.value, 10))){
+ html.addClass(node, "dojoxGridWardButton");
+ var disablePageNum = node.value == "prevPage" || node.value == "firstPage" ? 1 : pageCount;
+ updateClass(node, true, (curPage === disablePageNum));
+ }else{
+ value = parseInt(node.value, 10);
+ updateClass(node, false, (value === curPage || html.style(node, "display") === "none"));
+ }
+ }, this);
+ },
+ _showGotoButton: function(flag){
+ this.gotoButton = flag;
+ this._updateGotoButton();
+ },
+ _updateGotoButton: function(){
+ // summary:
+ // Create/destroy the goto page button
+ if(!this.gotoButton){
+ if(this._gotoPageDialog){
+ this._gotoPageDialog.destroy();
+ }
+ html.removeAttr(this.gotoPageDiv, "tabindex");
+ html.style(this.gotoPageTd, 'display', 'none');
+ return;
+ }
+ if(html.style(this.gotoPageTd, 'display') == 'none'){
+ html.style(this.gotoPageTd, 'display', '');
+ }
+ this.gotoPageDiv.setAttribute('title', this.plugin._nls[10]);
+ html.toggleClass(this.gotoPageDiv, "dojoxGridPaginatorGotoDivDisabled", this.plugin.getTotalPageNum() <= 1);
+ if(this.plugin.getTotalPageNum() <= 1){
+ html.removeAttr(this.gotoPageDiv, "tabindex");
+ }else{
+ this.gotoPageDiv.setAttribute("tabindex", "-3");
+ }
+ },
+ _openGotopageDialog: function(e){
+ // summary:
+ // Show the goto page dialog
+ if(this.plugin.getTotalPageNum() <= 1){
+ return;
+ }
+ if(e.type === "keydown" && e.keyCode !== keys.ENTER && e.keyCode !== keys.SPACE){
+ return;
+ }
+ if(!this._gotoPageDialog){
+ this._gotoPageDialog = new _GotoPageDialog(this.plugin);
+ }
+ this._gotoPageDialog.showDialog();
+ this.onShowGotoPageDialog(e);
+ },
+ _onSwitchPageSize: function(/*Event*/e){
+ // summary:
+ // The handler of switch the page size
+ if(e.type === "keydown" && e.keyCode !== keys.ENTER && e.keyCode !== keys.SPACE){
+ return;
+ }
+ this.onSwitchPageSize(e);
+ this.plugin.currentPageSize(e.target.value);
+ },
+ _onPageStep: function(/*Event*/e){
+ // summary:
+ // The handler jump page event
+ if(e.type === "keydown" && e.keyCode !== keys.ENTER && e.keyCode !== keys.SPACE){
+ return;
+ }
+ var p = this.plugin,
+ value = e.target.value;
+ this.onPageStep(e);
+ if(!isNaN(parseInt(value, 10))){
+ p.currentPage(parseInt(value, 10));
+ }else{
+ p[value]();
+ }
+ },
+ _getStartPage: function(){
+ var cp = this.plugin.currentPage(),
+ ms = this.maxPageStep,
+ hs = parseInt(ms / 2, 10),
+ tp = this.plugin.getTotalPageNum();
+ if(cp < hs || (cp - hs) < 1 || tp <= ms){
+ return 1;
+ }else{
+ return tp - cp < hs && cp - ms >= 0 ? tp - ms + 1 : cp - hs;
+ }
+ },
+ _getStepPageSize: function(){
+ var sp = this._getStartPage(),
+ tp = this.plugin.getTotalPageNum(),
+ ms = this.maxPageStep;
+ return sp + ms > tp ? tp - sp + 1 : ms;
+ }
+});
+
+var Pagination = declare("dojox.grid.enhanced.plugins.Pagination", _Plugin, {
+ // summary:
+ // The typical pagination way to deal with huge dataset
+ // an alternative for the default virtual scrolling manner.
+ name: "pagination",
+ // defaultPageSize: Integer
+ // Number of rows in a page, 25 by default.
+ defaultPageSize: 25,
+ // defaultPage: Integer
+ // Which page will be displayed initially, 1st page by default.
+ defaultPage: 1,
+ // description: boolean
+ // Whether the description information will be displayed, true by default.
+ description: true,
+ // sizeSwitch: boolean
+ // Whether the page size switch options will be displayed, true by default.
+ sizeSwitch: true,
+ // pageStepper: boolean
+ // Whether the page switch options will be displayed, true by default.
+ pageStepper: true,
+ // gotoButton: boolean
+ // Whether the goto page button will be displayed, false by default.
+ gotoButton: false,
+ // pageSizes: Array
+ // Array of page sizes for switching, e.g. [10, 25, 50, 100, Infinity] by default,
+ // Infinity or any NaN value will be treated as "all".
+ pageSizes: [10, 25, 50, 100, Infinity],
+ // maxPageStep: Integer
+ // The max number of page sizes to be displayed, 7 by default.
+ maxPageStep: 7,
+ // position: string
+ // The position of the pagination bar - "top"|"bottom", "bottom" by default.
+ position: 'bottom',
+
+ init: function(){
+ var g = this.grid;
+ g.usingPagination = true;
+ this._initOptions();
+ this._currentPage = this.defaultPage;
+ this._currentPageSize = this.grid.rowsPerPage = this.defaultPageSize;
+ // wrap store layer
+ this._store = g.store;
+ this.forcePageStoreLayer = new _ForcedPageStoreLayer(this);
+ layers.wrap(g, "_storeLayerFetch", this.forcePageStoreLayer);
+ // create pagination bar
+ this._paginator = this.option.position != "top" ?
+ new _Paginator(lang.mixin(this.option, {position: "bottom", plugin: this})) :
+ new _Paginator(lang.mixin(this.option, {position: "top", plugin: this}));
+ this._regApis();
+ },
+ destroy: function(){
+ this.inherited(arguments);
+ this._paginator.destroy();
+ var g = this.grid;
+ g.unwrap(this.forcePageStoreLayer.name());
+ g.scrollToRow = this._gridOriginalfuncs[0];
+ g._onNew = this._gridOriginalfuncs[1];
+ g.removeSelectedRows = this._gridOriginalfuncs[2];
+ this._paginator = null;
+ this._nls = null;
+ },
+ currentPage: function(page){
+ // summary:
+ // Shift to the given page, return current page number. If there
+ // is no valid page was passed in, just return current page num.
+ // page: Integer
+ // The page to go to, starting at 1.
+ // return:
+ // Current page number
+ if(page <= this.getTotalPageNum() && page > 0 && this._currentPage !== page){
+ this._currentPage = page;
+ this.grid._refresh(true);
+ this.grid.resize();
+ }
+ return this._currentPage;
+ },
+ nextPage: function(){
+ // summary:
+ // Go to the next page.
+ this.currentPage(this._currentPage + 1);
+ },
+ prevPage: function(){
+ // summary:
+ // Go to the previous page.
+ this.currentPage(this._currentPage - 1);
+ },
+ firstPage: function(){
+ // summary:
+ // Go to the first page
+ this.currentPage(1);
+ },
+ lastPage: function(){
+ // summary:
+ // Go to the last page
+ this.currentPage(this.getTotalPageNum());
+ },
+ currentPageSize: function(size){
+ // summary:
+ // Change the size of current page or return the current page size.
+ // size: Integer || null
+ // An integer identifying the number of rows per page. If the size
+ // is an Infinity, all rows will be displayed; if an invalid value pssed
+ // in, the current page size will be returned.
+ // return
+ // Current size of items per page.
+ if(!isNaN(size)){
+ var g = this.grid,
+ startIndex = this._currentPageSize * (this._currentPage - 1), endIndex;
+ this._showAll = !isFinite(size);
+ this.grid.usingPagination = !this._showAll;
+ this._currentPageSize = this._showAll ? this._maxSize : size;
+ g.rowsPerPage = this._showAll ? this._defaultRowsPerPage : size;
+ endIndex = startIndex + Math.min(this._currentPageSize, this._maxSize);
+ if(endIndex > this._maxSize){
+ this.lastPage();
+ }else{
+ var cp = Math.ceil(startIndex / this._currentPageSize) + 1;
+ if(cp !== this._currentPage){
+ this.currentPage(cp);
+ }else{
+ this.grid._refresh(true);
+ }
+ }
+ this.grid.resize();
+ }
+ return this._currentPageSize;
+ },
+ getTotalPageNum: function(){
+ // summary:
+ // Get total page number
+ return Math.ceil(this._maxSize / this._currentPageSize);
+ },
+ getTotalRowCount: function(){
+ // summary:
+ // Function for get total row count
+ return this._maxSize;
+ },
+ scrollToRow: function(inRowIndex){
+ // summary:
+ // Override the grid.scrollToRow(), could jump to the right page
+ // and scroll to the specific row
+ // inRowIndex: integer
+ // The row index
+ var page = parseInt(inRowIndex / this._currentPageSize, 10) + 1;
+ if(page > this.getTotalPageNum()){
+ return;
+ }
+ this.currentPage(page);
+ var rowIdx = inRowIndex % this._currentPageSize;
+ return this._gridOriginalfuncs[0](rowIdx);
+ },
+ removeSelectedRows: function(){
+ this._multiRemoving = true;
+ this._gridOriginalfuncs[2].apply();
+ this._multiRemoving = false;
+ this.grid.resize();
+ this.grid._refresh();
+ },
+ showGotoPageButton: function(flag){
+ // summary:
+ // For show/hide the go to page button dynamically
+ // flag: boolean
+ // Show the go to page button when flag is true, otherwise hide it
+ this._paginator.gotoButton = flag;
+ this._paginator._updateGotoButton();
+ },
+ // [DEPRECATED] ============
+ gotoPage: function(page){
+ kernel.deprecated("dojox.grid.enhanced.EnhancedGrid.gotoPage(page)", "use dojox.grid.enhanced.EnhancedGrid.currentPage(page) instead", "1.8");
+ this.currentPage(page);
+ },
+ gotoFirstPage: function(){
+ kernel.deprecated("dojox.grid.enhanced.EnhancedGrid.gotoFirstPage()", "use dojox.grid.enhanced.EnhancedGrid.firstPage() instead", "1.8");
+ this.firstPage();
+ },
+ gotoLastPage: function(){
+ kernel.deprecated("dojox.grid.enhanced.EnhancedGrid.gotoLastPage()", "use dojox.grid.enhanced.EnhancedGrid.lastPage() instead", "1.8");
+ this.lastPage();
+ },
+ changePageSize: function(size){
+ kernel.deprecated("dojox.grid.enhanced.EnhancedGrid.changePageSize(size)", "use dojox.grid.enhanced.EnhancedGrid.currentPageSize(size) instead", "1.8");
+ this.currentPageSize(size);
+ },
+ // =============== Protected ================
+ _nls: null,
+ _showAll: false,
+ _maxSize: 0,
+ // =============== Private ===============
+ _defaultRowsPerPage: 25,
+ _currentPage: 1,
+ _currentPageSize: 25,
+
+ _initOptions: function(){
+ this._defaultRowsPerPage = this.grid.rowsPerPage || 25;
+ this.defaultPage = this.option.defaultPage >= 1 ? parseInt(this.option.defaultPage, 10) : 1;
+ this.option.description = this.option.description !== undefined ? !!this.option.description : this.description;
+ this.option.sizeSwitch = this.option.sizeSwitch !== undefined ? !!this.option.sizeSwitch : this.sizeSwitch;
+ this.option.pageStepper = this.option.pageStepper !== undefined ? !!this.option.pageStepper : this.pageStepper;
+ this.option.gotoButton = this.option.gotoButton !== undefined ? !!this.option.gotoButton : this.gotoButton;
+ if(lang.isArray(this.option.pageSizes)){
+ var pageSizes = [];
+ array.forEach(this.option.pageSizes, function(size){
+ size = typeof size == 'number' ? size : parseInt(size, 10);
+ if(!isNaN(size) && size > 0){
+ pageSizes.push(size);
+ }else if(array.indexOf(pageSizes, Infinity) < 0){
+ pageSizes.push(Infinity);
+ }
+ }, this);
+ this.option.pageSizes = pageSizes.sort(function(a, b){return a - b;});
+ }else{
+ this.option.pageSizes = this.pageSizes;
+ }
+ this.defaultPageSize = this.option.defaultPageSize >= 1 ? parseInt(this.option.defaultPageSize, 10) : this.pageSizes[0];
+ this.option.maxPageStep = this.option.maxPageStep > 0 ? this.option.maxPageStep : this.maxPageStep;
+ this.option.position = lang.isString(this.option.position) ? this.option.position.toLowerCase() : this.position;
+ var nls = i18n.getLocalization("dojox.grid.enhanced", "Pagination");
+ this._nls = [
+ nls.descTemplate,
+ nls.allItemsLabelTemplate,
+ nls.pageSizeLabelTemplate,
+ nls.pageStepLabelTemplate,
+ nls.itemTitle,
+ nls.singularItemTitle,
+ nls.prevTip,
+ nls.firstTip,
+ nls.nextTip,
+ nls.lastTip,
+ nls.gotoButtonTitle,
+ nls.dialogTitle,
+ nls.dialogIndication,
+ nls.pageCountIndication,
+ nls.dialogConfirm,
+ nls.dialogCancel,
+ nls.all
+ ];
+ },
+ _regApis: function(){
+ var g = this.grid;
+ // New added APIs
+ g.currentPage = lang.hitch(this, this.currentPage);
+ g.nextPage = lang.hitch(this, this.nextPage);
+ g.prevPage = lang.hitch(this, this.prevPage);
+ g.firstPage = lang.hitch(this, this.firstPage);
+ g.lastPage = lang.hitch(this, this.lastPage);
+ g.currentPageSize = lang.hitch(this, this.currentPageSize);
+ g.showGotoPageButton = lang.hitch(this, this.showGotoPageButton);
+ g.getTotalRowCount = lang.hitch(this, this.getTotalRowCount);
+ g.getTotalPageNum = lang.hitch(this, this.getTotalPageNum);
+
+ g.gotoPage = lang.hitch(this, this.gotoPage);
+ g.gotoFirstPage = lang.hitch(this, this.gotoFirstPage);
+ g.gotoLastPage = lang.hitch(this, this.gotoLastPage);
+ g.changePageSize = lang.hitch(this, this.changePageSize);
+ // Changed APIs
+ this._gridOriginalfuncs = [
+ lang.hitch(g, g.scrollToRow),
+ lang.hitch(g, g._onNew),
+ lang.hitch(g, g.removeSelectedRows)
+ ];
+ g.scrollToRow = lang.hitch(this, this.scrollToRow);
+ g.removeSelectedRows = lang.hitch(this, this.removeSelectedRows);
+ g._onNew = lang.hitch(this, this._onNew);
+ this.connect(g, "_onDelete", lang.hitch(this, this._onDelete));
+ },
+ _onNew: function(item, parentInfo){
+ var totalPages = this.getTotalPageNum();
+ if(((this._currentPage === totalPages || totalPages === 0) && this.grid.get('rowCount') < this._currentPageSize) || this._showAll){
+ lang.hitch(this.grid, this._gridOriginalfuncs[1])(item, parentInfo);
+ this.forcePageStoreLayer.endIdx++;
+ }
+ this._maxSize++;
+ if(this._showAll){
+ this._currentPageSize++;
+ }
+ if(this._showAll && this.grid.autoHeight){
+ this.grid._refresh();
+ }else{
+ this._paginator._update();
+ }
+ },
+ _onDelete: function(){
+ if(!this._multiRemoving){
+ this.grid.resize();
+ if(this._showAll){
+ this.grid._refresh();
+ }
+ }
+ if(this.grid.get('rowCount') === 0){
+ this.prevPage();
+ }
+ }
+});
+
+EnhancedGrid.registerPlugin(Pagination/*name:'pagination'*/);
+
+return Pagination;
+
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/plugins/Printer.js b/js/dojo/dojox/grid/enhanced/plugins/Printer.js
new file mode 100644
index 0000000..09ab390
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/Printer.js
@@ -0,0 +1,292 @@
+//>>built
+define("dojox/grid/enhanced/plugins/Printer", [
+ "dojo/_base/declare",
+ "dojo/_base/html",
+ "dojo/_base/Deferred",
+ "dojo/_base/lang",
+ "dojo/_base/sniff",
+ "dojo/_base/xhr",
+ "dojo/_base/array",
+ "dojo/query",
+ "dojo/DeferredList",
+ "../_Plugin",
+ "../../EnhancedGrid",
+ "./exporter/TableWriter"
+], function(declare, html, Deferred, lang, has, xhr, array, query, DeferredList, _Plugin, EnhancedGrid, TableWriter){
+
+var Printer = declare("dojox.grid.enhanced.plugins.Printer", _Plugin, {
+ // summary:
+ // Provide printGrid function to the grid.
+ // example:
+ // | dojo.require("dojox.grid.enhanced.plugins.Printer");
+ // | dijit.byId("grid1").printGrid("my grid", //A title for the grid,optional
+ // | ["cssfile1.css","cssfile2.css"],//An array of css files to decorate the printed gird,optional
+ // | {table:"border='border'"} //tagName:"attrbuteList" pairs, optional,
+ // | //control the html tags in the generated html
+ // | );
+
+ // __printArgs: {
+ // title: String
+ // A title of the printed page can be specified. Optional.
+ // If given, it's shown in an <h1> tag at the top of the page.
+ // cssFiles: Array | String
+ // CSS file paths. Optional.
+ // Every row and column is given CSS classes, including:
+ // grid_row_{row-number}, grid_odd_row, grid_even_row, grid_header,
+ // grid_col_{col-number}, grid_odd_col, grid_even_col
+ // {row_number} and {col-number} are both integers starting from 1.
+ // Row classes are for <thead> and <tbody> tags.
+ // Column classes are for <th> and <td> tags.
+ // Users can use these classes in the CSS files, but cannot define their own.
+ // writerArgs: Object (Association Array)
+ // Arguments for TableWriter.
+ // fetchArgs: object?
+ // Any arguments for store.fetch
+ // }
+
+ // name: String
+ // Plugin name
+ name: "printer",
+
+ constructor: function(grid){
+ // summary:
+ // only newed by _Plugin
+ // inGrid: EnhancedGrid
+ // The grid to plug in to.
+ this.grid = grid;
+ this._mixinGrid(grid);
+
+ //For print, we usually need the HTML instead of raw data.
+ grid.setExportFormatter(function(data, cell, rowIndex, rowItem){
+ return cell.format(rowIndex, rowItem);
+ });
+ },
+ _mixinGrid: function(){
+ var g = this.grid;
+ g.printGrid = lang.hitch(this, this.printGrid);
+ g.printSelected = lang.hitch(this, this.printSelected);
+ g.exportToHTML = lang.hitch(this, this.exportToHTML);
+ g.exportSelectedToHTML = lang.hitch(this, this.exportSelectedToHTML);
+ g.normalizePrintedGrid = lang.hitch(this, this.normalizeRowHeight);
+ },
+ printGrid: function(args){
+ // summary:
+ // Print all the data in the grid, using title as a title,
+ // decorating generated html by cssFiles,
+ // using tagName:"attrbuteList" pairs(writerArgs) to control html tags
+ // in the generated html string.
+ // tags:
+ // public
+ // args: __printArgs?
+ // Arguments for print.
+ this.exportToHTML(args, lang.hitch(this, this._print));
+ },
+ printSelected: function(args){
+ // summary:
+ // Print selected data. All other features are the same as printGrid.
+ // For meaning of arguments see function *printGrid*
+ // tags:
+ // public
+ // args: __printArgs?
+ // Arguments for print.
+ this.exportSelectedToHTML(args, lang.hitch(this, this._print));
+ },
+ exportToHTML: function(args, onExported){
+ // summary:
+ // Export to HTML string, but do NOT print.
+ // Users can use this to implement print preview.
+ // For meaning of the 1st-3rd arguments see function *printGrid*.
+ // tags:
+ // public
+ // args: __printArgs?
+ // Arguments for print.
+ // onExported: function(string)
+ // call back function
+ args = this._formalizeArgs(args);
+ var _this = this;
+ this.grid.exportGrid("table", args, function(str){
+ _this._wrapHTML(args.title, args.cssFiles, args.titleInBody + str).then(onExported);
+ });
+ },
+ exportSelectedToHTML: function(args, onExported){
+ // summary:
+ // Export selected rows to HTML string, but do NOT print.
+ // Users can use this to implement print preview.
+ // For meaning of arguments see function *printGrid*
+ // tags:
+ // public
+ // args: __printArgs?
+ // Arguments for print.
+ args = this._formalizeArgs(args);
+ var _this = this;
+ this.grid.exportSelected("table", args.writerArgs, function(str){
+ _this._wrapHTML(args.title, args.cssFiles, args.titleInBody + str).then(onExported);
+ });
+ },
+
+ _loadCSSFiles: function(cssFiles){
+ var dl = array.map(cssFiles, function(cssFile){
+ cssFile = lang.trim(cssFile);
+ if(cssFile.substring(cssFile.length - 4).toLowerCase() === '.css'){
+ return xhr.get({
+ url: cssFile
+ });
+ }else{
+ var d = new Deferred();
+ d.callback(cssFile);
+ return d;
+ }
+ });
+ return DeferredList.prototype.gatherResults(dl);
+ },
+ _print: function(/* string */htmlStr){
+ // summary:
+ // Do the print job.
+ // tags:
+ // private
+ // htmlStr: String
+ // The html content string to be printed.
+ // returns:
+ // undefined
+ var win, _this = this,
+ fillDoc = function(w){
+ var doc = w.document;
+ doc.open();
+ doc.write(htmlStr);
+ doc.close();
+ _this.normalizeRowHeight(doc);
+ };
+ if(!window.print){
+ //We don't have a print facility.
+ return;
+ }else if(has("chrome") || has("opera")){
+ //referred from dijit._editor.plugins.Print._print()
+ //In opera and chrome the iframe.contentWindow.print
+ //will also print the outside window. So we must create a
+ //stand-alone new window.
+ win = window.open("javascript: ''", "",
+ "status=0,menubar=0,location=0,toolbar=0,width=1,height=1,resizable=0,scrollbars=0");
+ fillDoc(win);
+ win.print();
+ //Opera will stop at this point, showing the popping-out window.
+ //If the user closes the window, the following codes will not execute.
+ //If the user returns focus to the main window, the print function
+ // is executed, but still a no-op.
+ win.close();
+ }else{
+ //Put private things in deeper namespace to avoid poluting grid namespace.
+ var fn = this._printFrame,
+ dn = this.grid.domNode;
+ if(!fn){
+ var frameId = dn.id + "_print_frame";
+ if(!(fn = html.byId(frameId))){
+ //create an iframe to store the grid data.
+ fn = html.create("iframe");
+ fn.id = frameId;
+ fn.frameBorder = 0;
+ html.style(fn, {
+ width: "1px",
+ height: "1px",
+ position: "absolute",
+ right: 0,
+ bottom: 0,
+ border: "none",
+ overflow: "hidden"
+ });
+ if(!has("ie")){
+ html.style(fn, "visibility", "hidden");
+ }
+ dn.appendChild(fn);
+ }
+ //Reuse this iframe
+ this._printFrame = fn;
+ }
+ win = fn.contentWindow;
+ fillDoc(win);
+ //IE requires the frame to be focused for print to work, and it's harmless for FF.
+ win.focus();
+ win.print();
+ }
+ },
+ _wrapHTML: function(/* string */title, /* Array */cssFiles, /* string */body_content){
+ // summary:
+ // Put title, cssFiles, and body_content together into an HTML string.
+ // tags:
+ // private
+ // title: String
+ // A title for the html page.
+ // cssFiles: Array
+ // css file pathes.
+ // body_content: String
+ // Content to print, not including <head></head> part and <html> tags
+ // returns:
+ // the wrapped HTML string ready for print
+ return this._loadCSSFiles(cssFiles).then(function(cssStrs){
+ var i, sb = ['<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
+ '<html ', html._isBodyLtr() ? '' : 'dir="rtl"', '><head><title>', title,
+ '</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>'];
+ for(i = 0; i < cssStrs.length; ++i){
+ sb.push('<style type="text/css">', cssStrs[i], '</style>');
+ }
+ sb.push('</head>');
+ if(body_content.search(/^\s*<body/i) < 0){
+ body_content = '<body>' + body_content + '</body>';
+ }
+ sb.push(body_content, '</html>');
+ return sb.join('');
+ });
+ },
+ normalizeRowHeight: function(doc){
+ var views = query(".grid_view", doc.body);
+ var headPerView = array.map(views, function(view){
+ return query(".grid_header", view)[0];
+ });
+ var rowsPerView = array.map(views, function(view){
+ return query(".grid_row", view);
+ });
+ var rowCount = rowsPerView[0].length;
+ var i, v, h, maxHeight = 0;
+ for(v = views.length - 1; v >= 0; --v){
+ h = html.contentBox(headPerView[v]).h;
+ if(h > maxHeight){
+ maxHeight = h;
+ }
+ }
+ for(v = views.length - 1; v >= 0; --v){
+ html.style(headPerView[v], "height", maxHeight + "px");
+ }
+ for(i = 0; i < rowCount; ++i){
+ maxHeight = 0;
+ for(v = views.length - 1; v >= 0; --v){
+ h = html.contentBox(rowsPerView[v][i]).h;
+ if(h > maxHeight){
+ maxHeight = h;
+ }
+ }
+ for(v = views.length - 1; v >= 0; --v){
+ html.style(rowsPerView[v][i], "height", maxHeight + "px");
+ }
+ }
+ var left = 0, ltr = html._isBodyLtr();
+ for(v = 0; v < views.length; ++v){
+ html.style(views[v], ltr ? "left" : "right", left + "px");
+ left += html.marginBox(views[v]).w;
+ }
+ },
+ _formalizeArgs: function(args){
+ args = (args && lang.isObject(args)) ? args : {};
+ args.title = String(args.title) || "";
+ if(!lang.isArray(args.cssFiles)){
+ args.cssFiles = [args.cssFiles];
+ }
+ args.titleInBody = args.title ? ['<h1>', args.title, '</h1>'].join('') : '';
+ return args; //Object
+ }
+});
+
+EnhancedGrid.registerPlugin(Printer/*name:'printer'*/, {
+ "dependency": ["exporter"]
+});
+
+return Printer;
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/Rearrange.js b/js/dojo/dojox/grid/enhanced/plugins/Rearrange.js
new file mode 100644
index 0000000..1c3bac3
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/Rearrange.js
@@ -0,0 +1,506 @@
+//>>built
+define("dojox/grid/enhanced/plugins/Rearrange", [
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "../../EnhancedGrid",
+ "../_Plugin",
+ "./_RowMapLayer"
+], function(dojo, lang, declare, array, connect, EnhancedGrid, _Plugin, _RowMapLayer){
+
+var Rearrange = declare("dojox.grid.enhanced.plugins.Rearrange", _Plugin, {
+ // summary:
+ // Provides a set of method to re-arrange the structure of grid.
+
+ // name: String
+ // plugin name
+ name: "rearrange",
+
+ constructor: function(grid, args){
+ this.grid = grid;
+ this.setArgs(args);
+ var rowMapLayer = new _RowMapLayer(grid);
+ dojox.grid.enhanced.plugins.wrap(grid, "_storeLayerFetch", rowMapLayer);
+ },
+ setArgs: function(args){
+ this.args = lang.mixin(this.args || {}, args || {});
+ this.args.setIdentifierForNewItem = this.args.setIdentifierForNewItem || function(v){return v;};
+ },
+ destroy: function(){
+ this.inherited(arguments);
+ this.grid.unwrap("rowmap");
+ },
+ onSetStore: function(store){
+ this.grid.layer("rowmap").clearMapping();
+ },
+ _hasIdentity: function(points){
+ var g = this.grid, s = g.store, cells = g.layout.cells;
+ if(s.getFeatures()["dojo.data.api.Identity"]){
+ if(array.some(points, function(point){
+ return s.getIdentityAttributes(g._by_idx[point.r].item) == cells[point.c].field;
+ })){
+ return true;
+ }
+ }
+ return false;
+ },
+ moveColumns: function(colsToMove, targetPos){
+ // summary:
+ // Move a set of columns to a given position.
+ // tag:
+ // public
+ // colsToMove: Integer[]
+ // Array of column indexes.
+ // targetPos: Integer
+ // The target position
+ var g = this.grid,
+ layout = g.layout,
+ cells = layout.cells,
+ colIndex, i, delta = 0,
+ before = true, tmp = {}, mapping = {};
+ colsToMove.sort(function(a, b){
+ return a - b;
+ });
+ for(i = 0; i < colsToMove.length; ++i){
+ tmp[colsToMove[i]] = i;
+ if(colsToMove[i] < targetPos){
+ ++delta;
+ }
+ }
+ var leftCount = 0, rightCount = 0;
+ var maxCol = Math.max(colsToMove[colsToMove.length - 1], targetPos);
+ if(maxCol == cells.length){
+ --maxCol;
+ }
+ var minCol = Math.min(colsToMove[0], targetPos);
+ for(i = minCol; i <= maxCol; ++i){
+ var j = tmp[i];
+ if(j >= 0){
+ mapping[i] = targetPos - delta + j;
+ }else if(i < targetPos){
+ mapping[i] = minCol + leftCount;
+ ++leftCount;
+ }else if(i >= targetPos){
+ mapping[i] = targetPos + colsToMove.length - delta + rightCount;
+ ++rightCount;
+ }
+ }
+ //console.log("mapping:", mapping, ", colsToMove:", colsToMove,", target:", targetPos);
+ delta = 0;
+ if(targetPos == cells.length){
+ --targetPos;
+ before = false;
+ }
+ g._notRefreshSelection = true;
+ for(i = 0; i < colsToMove.length; ++i){
+ colIndex = colsToMove[i];
+ if(colIndex < targetPos){
+ colIndex -= delta;
+ }
+ ++delta;
+ if(colIndex != targetPos){
+ layout.moveColumn(cells[colIndex].view.idx, cells[targetPos].view.idx, colIndex, targetPos, before);
+ cells = layout.cells;
+ }
+ if(targetPos <= colIndex){
+ ++targetPos;
+ }
+ }
+ delete g._notRefreshSelection;
+ connect.publish("dojox/grid/rearrange/move/" + g.id, ["col", mapping, colsToMove]);
+ },
+ moveRows: function(rowsToMove, targetPos){
+ // summary:
+ // Move a set of rows to a given position
+ // tag:
+ // public
+ // rowsToMove: Integer[]
+ // Array of row indexes.
+ // targetPos: Integer
+ // The target position
+ var g = this.grid,
+ mapping = {},
+ preRowsToMove = [],
+ postRowsToMove = [],
+ len = rowsToMove.length,
+ i, r, k, arr, rowMap, lastPos;
+
+ for(i = 0; i < len; ++i){
+ r = rowsToMove[i];
+ if(r >= targetPos){
+ break;
+ }
+ preRowsToMove.push(r);
+ }
+ postRowsToMove = rowsToMove.slice(i);
+
+ arr = preRowsToMove;
+ len = arr.length;
+ if(len){
+ rowMap = {};
+ array.forEach(arr, function(r){
+ rowMap[r] = true;
+ });
+ mapping[arr[0]] = targetPos - len;
+ for(k = 0, i = arr[k] + 1, lastPos = i - 1; i < targetPos; ++i){
+ if(!rowMap[i]){
+ mapping[i] = lastPos;
+ ++lastPos;
+ }else{
+ ++k;
+ mapping[i] = targetPos - len + k;
+ }
+ }
+ }
+ arr = postRowsToMove;
+ len = arr.length;
+ if(len){
+ rowMap = {};
+ array.forEach(arr, function(r){
+ rowMap[r] = true;
+ });
+ mapping[arr[len - 1]] = targetPos + len - 1;
+ for(k = len - 1, i = arr[k] - 1, lastPos = i + 1; i >= targetPos; --i){
+ if(!rowMap[i]){
+ mapping[i] = lastPos;
+ --lastPos;
+ }else{
+ --k;
+ mapping[i] = targetPos + k;
+ }
+ }
+ }
+ var tmpMapping = lang.clone(mapping);
+ g.layer("rowmap").setMapping(mapping);
+ g.forEachLayer(function(layer){
+ if(layer.name() != "rowmap"){
+ layer.invalidate();
+ return true;
+ }else{
+ return false;
+ }
+ }, false);
+ g.selection.selected = [];
+ g._noInternalMapping = true;
+ g._refresh();
+ setTimeout(function(){
+ connect.publish("dojox/grid/rearrange/move/" + g.id, ["row", tmpMapping, rowsToMove]);
+ g._noInternalMapping = false;
+ }, 0);
+ },
+ moveCells: function(cellsToMove, target){
+ var g = this.grid,
+ s = g.store;
+ if(s.getFeatures()["dojo.data.api.Write"]){
+ if(cellsToMove.min.row == target.min.row && cellsToMove.min.col == target.min.col){
+ //Same position, no need to move
+ return;
+ }
+ var cells = g.layout.cells,
+ cnt = cellsToMove.max.row - cellsToMove.min.row + 1,
+ r, c, tr, tc,
+ sources = [], targets = [];
+ for(r = cellsToMove.min.row, tr = target.min.row; r <= cellsToMove.max.row; ++r, ++tr){
+ for(c = cellsToMove.min.col, tc = target.min.col; c <= cellsToMove.max.col; ++c, ++tc){
+ while(cells[c] && cells[c].hidden){
+ ++c;
+ }
+ while(cells[tc] && cells[tc].hidden){
+ ++tc;
+ }
+ sources.push({
+ "r": r,
+ "c": c
+ });
+ targets.push({
+ "r": tr,
+ "c": tc,
+ "v": cells[c].get(r, g._by_idx[r].item)
+ });
+ }
+ }
+ if(this._hasIdentity(sources.concat(targets))){
+ console.warn("Can not write to identity!");
+ return;
+ }
+ array.forEach(sources, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, "");
+ });
+ array.forEach(targets, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, point.v);
+ });
+ s.save({
+ onComplete: function(){
+ connect.publish("dojox/grid/rearrange/move/" + g.id, ["cell", {
+ "from": cellsToMove,
+ "to": target
+ }]);
+ }
+ });
+ }
+ },
+ copyCells: function(cellsToMove, target){
+ var g = this.grid,
+ s = g.store;
+ if(s.getFeatures()["dojo.data.api.Write"]){
+ if(cellsToMove.min.row == target.min.row && cellsToMove.min.col == target.min.col){
+ return;
+ }
+ var cells = g.layout.cells,
+ cnt = cellsToMove.max.row - cellsToMove.min.row + 1,
+ r, c, tr, tc,
+ targets = [];
+ for(r = cellsToMove.min.row, tr = target.min.row; r <= cellsToMove.max.row; ++r, ++tr){
+ for(c = cellsToMove.min.col, tc = target.min.col; c <= cellsToMove.max.col; ++c, ++tc){
+ while(cells[c] && cells[c].hidden){
+ ++c;
+ }
+ while(cells[tc] && cells[tc].hidden){
+ ++tc;
+ }
+ targets.push({
+ "r": tr,
+ "c": tc,
+ "v": cells[c].get(r, g._by_idx[r].item)
+ });
+ }
+ }
+ if(this._hasIdentity(targets)){
+ console.warn("Can not write to identity!");
+ return;
+ }
+ array.forEach(targets, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, point.v);
+ });
+ s.save({
+ onComplete: function(){
+ setTimeout(function(){
+ connect.publish("dojox/grid/rearrange/copy/" + g.id, ["cell", {
+ "from": cellsToMove,
+ "to": target
+ }]);
+ }, 0);
+ }
+ });
+ }
+ },
+ changeCells: function(sourceGrid, cellsToMove, target){
+ var g = this.grid,
+ s = g.store;
+ if(s.getFeatures()["dojo.data.api.Write"]){
+ var srcg = sourceGrid,
+ cells = g.layout.cells,
+ srccells = srcg.layout.cells,
+ cnt = cellsToMove.max.row - cellsToMove.min.row + 1,
+ r, c, tr, tc, targets = [];
+ for(r = cellsToMove.min.row, tr = target.min.row; r <= cellsToMove.max.row; ++r, ++tr){
+ for(c = cellsToMove.min.col, tc = target.min.col; c <= cellsToMove.max.col; ++c, ++tc){
+ while(srccells[c] && srccells[c].hidden){
+ ++c;
+ }
+ while(cells[tc] && cells[tc].hidden){
+ ++tc;
+ }
+ targets.push({
+ "r": tr,
+ "c": tc,
+ "v": srccells[c].get(r, srcg._by_idx[r].item)
+ });
+ }
+ }
+ if(this._hasIdentity(targets)){
+ console.warn("Can not write to identity!");
+ return;
+ }
+ array.forEach(targets, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, point.v);
+ });
+ s.save({
+ onComplete: function(){
+ connect.publish("dojox/grid/rearrange/change/" + g.id, ["cell", target]);
+ }
+ });
+ }
+ },
+ clearCells: function(cellsToClear){
+ var g = this.grid,
+ s = g.store;
+ if(s.getFeatures()["dojo.data.api.Write"]){
+ var cells = g.layout.cells,
+ cnt = cellsToClear.max.row - cellsToClear.min.row + 1,
+ r, c, targets = [];
+ for(r = cellsToClear.min.row; r <= cellsToClear.max.row; ++r){
+ for(c = cellsToClear.min.col; c <= cellsToClear.max.col; ++c){
+ while(cells[c] && cells[c].hidden){
+ ++c;
+ }
+ targets.push({
+ "r": r,
+ "c": c
+ });
+ }
+ }
+ if(this._hasIdentity(targets)){
+ console.warn("Can not write to identity!");
+ return;
+ }
+ array.forEach(targets, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, "");
+ });
+ s.save({
+ onComplete: function(){
+ connect.publish("dojox/grid/rearrange/change/" + g.id, ["cell", cellsToClear]);
+ }
+ });
+ }
+ },
+ insertRows: function(sourceGrid, rowsToMove, targetPos){
+ try{
+ var g = this.grid,
+ s = g.store,
+ rowCnt = g.rowCount,
+ mapping = {},
+ obj = {idx: 0},
+ newRows = [], i,
+ emptyTarget = targetPos < 0;
+ _this = this;
+ var len = rowsToMove.length;
+ if(emptyTarget){
+ targetPos = 0;
+ }else{
+ for(i = targetPos; i < g.rowCount; ++i){
+ mapping[i] = i + len;
+ }
+ }
+ if(s.getFeatures()['dojo.data.api.Write']){
+ if(sourceGrid){
+ var srcg = sourceGrid,
+ srcs = srcg.store,
+ thisItem, attrs;
+ if(!emptyTarget){
+ for(i = 0; !thisItem; ++i){
+ thisItem = g._by_idx[i];
+ }
+ attrs = s.getAttributes(thisItem.item);
+ }else{
+ //If the target grid is empty, there is no way to retrieve attributes.
+ //So try to get attrs from grid.layout.cells[], but this might not be right
+ //since some fields may be missed(e.g ID fields), please use "setIdentifierForNewItem()"
+ //to add those missed fields
+ attrs = array.map(g.layout.cells, function(cell){
+ return cell.field;
+ });
+ }
+ var rowsToFetch = [];
+ array.forEach(rowsToMove, function(rowIndex, i){
+ var item = {};
+ var srcItem = srcg._by_idx[rowIndex];
+ if(srcItem){
+ array.forEach(attrs, function(attr){
+ item[attr] = srcs.getValue(srcItem.item, attr);
+ });
+ item = _this.args.setIdentifierForNewItem(item, s, rowCnt + obj.idx) || item;
+ try{
+ s.newItem(item);
+ newRows.push(targetPos + i);
+ mapping[rowCnt + obj.idx] = targetPos + i;
+ ++obj.idx;
+ }catch(e){
+ console.log("insertRows newItem:",e,item);
+ }
+ }else{
+ rowsToFetch.push(rowIndex);
+ }
+ });
+ }else if(rowsToMove.length && lang.isObject(rowsToMove[0])){
+ array.forEach(rowsToMove, function(rowData, i){
+ var item = _this.args.setIdentifierForNewItem(rowData, s, rowCnt + obj.idx) || rowData;
+ try{
+ s.newItem(item);
+ newRows.push(targetPos + i);
+ mapping[rowCnt + obj.idx] = targetPos + i;
+ ++obj.idx;
+ }catch(e){
+ console.log("insertRows newItem:",e,item);
+ }
+ });
+ }else{
+ return;
+ }
+ g.layer("rowmap").setMapping(mapping);
+ s.save({
+ onComplete: function(){
+ g._refresh();
+ setTimeout(function(){
+ connect.publish("dojox/grid/rearrange/insert/" + g.id, ["row", newRows]);
+ }, 0);
+ }
+ });
+ }
+ }catch(e){
+ console.log("insertRows:",e);
+ }
+ },
+ removeRows: function(rowsToRemove){
+ var g = this.grid;
+ var s = g.store;
+ try{
+ array.forEach(array.map(rowsToRemove, function(rowIndex){
+ return g._by_idx[rowIndex];
+ }), function(row){
+ if(row){
+ s.deleteItem(row.item);
+ }
+ });
+ s.save({
+ onComplete: function(){
+ connect.publish("dojox/grid/rearrange/remove/" + g.id, ["row", rowsToRemove]);
+ }
+ });
+ }catch(e){
+ console.log("removeRows:",e);
+ }
+ },
+ _getPageInfo: function(){
+ // summary:
+ // Find pages that contain visible rows
+ // return: Object
+ // {topPage: xx, bottomPage: xx, invalidPages: [xx,xx,...]}
+ var scroller = this.grid.scroller,
+ topPage = scroller.page,
+ bottomPage = scroller.page,
+ firstVisibleRow = scroller.firstVisibleRow,
+ lastVisibleRow = scroller.lastVisibleRow,
+ rowsPerPage = scroller.rowsPerPage,
+ renderedPages = scroller.pageNodes[0],
+ topRow, bottomRow, matched,
+ invalidPages = [];
+
+ array.forEach(renderedPages, function(page, pageIndex){
+ if(!page){ return; }
+ matched = false;
+ topRow = pageIndex * rowsPerPage;
+ bottomRow = (pageIndex + 1) * rowsPerPage - 1;
+ if(firstVisibleRow >= topRow && firstVisibleRow <= bottomRow){
+ topPage = pageIndex;
+ matched = true;
+ }
+ if(lastVisibleRow >= topRow && lastVisibleRow <= bottomRow){
+ bottomPage = pageIndex;
+ matched = true;
+ }
+ if(!matched && (topRow > lastVisibleRow || bottomRow < firstVisibleRow)){
+ invalidPages.push(pageIndex);
+ }
+ });
+ return {topPage: topPage, bottomPage: bottomPage, invalidPages: invalidPages};
+ }
+});
+
+EnhancedGrid.registerPlugin(Rearrange/*name:'rearrange'*/);
+
+return Rearrange;
+
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/plugins/Search.js b/js/dojo/dojox/grid/enhanced/plugins/Search.js
new file mode 100644
index 0000000..2c0284c
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/Search.js
@@ -0,0 +1,123 @@
+//>>built
+define("dojox/grid/enhanced/plugins/Search", [
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/data/util/filter",
+ "../../EnhancedGrid",
+ "../_Plugin"
+], function(dojo, lang, declare, array, dFilter, EnhancedGrid, _Plugin){
+
+var Search = declare("dojox.grid.enhanced.plugins.Search", _Plugin, {
+ // summary:
+ // Search the grid using wildcard string or Regular Expression.
+
+ // name: String
+ // plugin name
+ name: "search",
+
+ constructor: function(grid, args){
+ this.grid = grid;
+ args = (args && lang.isObject(args)) ? args : {};
+ this._cacheSize = args.cacheSize || -1;
+ grid.searchRow = lang.hitch(this, "searchRow");
+ },
+ searchRow: function(/* Object|RegExp|String */searchArgs, /* function(Integer, item) */onSearched){
+ if(!lang.isFunction(onSearched)){ return; }
+ if(lang.isString(searchArgs)){
+ searchArgs = dFilter.patternToRegExp(searchArgs);
+ }
+ var isGlobal = false;
+ if(searchArgs instanceof RegExp){
+ isGlobal = true;
+ }else if(lang.isObject(searchArgs)){
+ var isEmpty = true;
+ for(var field in searchArgs){
+ if(lang.isString(searchArgs[field])){
+ searchArgs[field] = dFilter.patternToRegExp(searchArgs[field]);
+ }
+ isEmpty = false;
+ }
+ if(isEmpty){ return; }
+ }else{
+ return;
+ }
+ this._search(searchArgs, 0, onSearched, isGlobal);
+ },
+ _search: function(/* Object|RegExp */searchArgs, /* Integer */start, /* function(Integer, item) */onSearched, /* Boolean */isGlobal){
+ var _this = this,
+ cnt = this._cacheSize,
+ args = {
+ start: start,
+ query: this.grid.query,
+ sort: this.grid.getSortProps(),
+ queryOptions: this.grid.queryOptions,
+ onBegin: function(size){
+ _this._storeSize = size;
+ },
+ onComplete: function(items){
+ if(!array.some(items, function(item, i){
+ if(_this._checkRow(item, searchArgs, isGlobal)){
+ onSearched(start + i, item);
+ return true;
+ }
+ return false;
+ })){
+ if(cnt > 0 && start + cnt < _this._storeSize){
+ _this._search(searchArgs, start + cnt, onSearched, isGlobal);
+ }else{
+ onSearched(-1, null);
+ }
+ }
+ }
+ };
+ if(cnt > 0){
+ args.count = cnt;
+ }
+ this.grid._storeLayerFetch(args);
+ },
+ _checkRow: function(/* store item */item, /* Object|RegExp */searchArgs, /* Boolean */isGlobal){
+ var g = this.grid, s = g.store, i, field,
+ cells = array.filter(g.layout.cells, function(cell){
+ return !cell.hidden;
+ });
+ if(isGlobal){
+ return array.some(cells, function(cell){
+ try{
+ if(cell.field){
+ return String(s.getValue(item, cell.field)).search(searchArgs) >= 0;
+ }
+ }catch(e){
+ console.log("Search._checkRow() error: ", e);
+ }
+ return false;
+ });
+ }else{
+ for(field in searchArgs){
+ if(searchArgs[field] instanceof RegExp){
+ for(i = cells.length - 1; i >= 0; --i){
+ if(cells[i].field == field){
+ try{
+ if(String(s.getValue(item, field)).search(searchArgs[field]) < 0){
+ return false;
+ }
+ break;
+ }catch(e){
+ return false;
+ }
+ }
+ }
+ if(i < 0){ return false; }
+ }
+ }
+ return true;
+ }
+ }
+});
+
+EnhancedGrid.registerPlugin(Search/*name:'search'*/);
+
+return Search;
+
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/plugins/Selector.js b/js/dojo/dojox/grid/enhanced/plugins/Selector.js
new file mode 100644
index 0000000..c9e2574
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/Selector.js
@@ -0,0 +1,1477 @@
+//>>built
+define("dojox/grid/enhanced/plugins/Selector", [
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ "dojo/keys",
+ "dojo/query",
+ "dojo/_base/html",
+ "dojo/_base/window",
+ "dijit/focus",
+ "../../_RowSelector",
+ "../_Plugin",
+ "../../EnhancedGrid",
+ "../../cells/_base",
+ "./AutoScroll"
+], function(dojo, lang, declare, array, event, keys, query, html, win, dijitFocus, _RowSelector, _Plugin, EnhancedGrid){
+
+/*=====
+dojo.declare("__SelectItem", null,{
+ // summary:
+ // An abstract representation of an item.
+});
+dojo.declare("__SelectCellItem", __SelectItem,{
+ // summary:
+ // An abstract representation of a cell.
+
+ // row: Integer
+ // Row index of this cell
+ row: 0,
+
+ // col: Integer
+ // Column index of this cell
+ col: 0
+});
+dojo.declare("__SelectRowItem", __SelectItem,{
+ // summary:
+ // An abstract representation of a row.
+
+ // row: Integer
+ // Row index of this row
+ row: 0,
+
+ // except: Integer[]
+ // An array of column indexes of all the unselected cells in this row.
+ except: []
+});
+dojo.declare("__SelectColItem", __SelectItem,{
+ // summary:
+ // An abstract representation of a column.
+
+ // col: Integer
+ // Column index of this column
+ col: 0,
+
+ // except: Integer[]
+ // An array of row indexes of all the unselected cells in this column.
+ except: []
+});
+=====*/
+
+var DISABLED = 0, SINGLE = 1, MULTI = 2,
+ _theOther = { col: "row", row: "col" },
+ _inRange = function(type, value, start, end, halfClose){
+ if(type !== "cell"){
+ value = value[type];
+ start = start[type];
+ end = end[type];
+ if(typeof value !== "number" || typeof start !== "number" || typeof end !== "number"){
+ return false;
+ }
+ return halfClose ? ((value >= start && value < end) || (value > end && value <= start))
+ : ((value >= start && value <= end) || (value >= end && value <= start));
+ }else{
+ return _inRange("col", value, start, end, halfClose) && _inRange("row", value, start, end, halfClose);
+ }
+ },
+ _isEqual = function(type, v1, v2){
+ try{
+ if(v1 && v2){
+ switch(type){
+ case "col": case "row":
+ return v1[type] == v2[type] && typeof v1[type] == "number" &&
+ !(_theOther[type] in v1) && !(_theOther[type] in v2);
+ case "cell":
+ return v1.col == v2.col && v1.row == v2.row && typeof v1.col == "number" && typeof v1.row == "number";
+ }
+ }
+ }catch(e){}
+ return false;
+ },
+ _stopEvent = function(evt){
+ try{
+ if(evt && evt.preventDefault){
+ event.stop(evt);
+ }
+ }catch(e){}
+ },
+ _createItem = function(type, rowIndex, colIndex){
+ switch(type){
+ case "col":
+ return {
+ "col": typeof colIndex == "undefined" ? rowIndex : colIndex,
+ "except": []
+ };
+ case "row":
+ return {
+ "row": rowIndex,
+ "except": []
+ };
+ case "cell":
+ return {
+ "row": rowIndex,
+ "col": colIndex
+ };
+ }
+ return null;
+ };
+var Selector = declare("dojox.grid.enhanced.plugins.Selector", _Plugin, {
+ // summary:
+ // Provides standard extended selection for grid.
+ // Supports mouse/keyboard selection, multi-selection, and de-selection.
+ // Acceptable plugin parameters:
+ // The whole plugin parameter object is a config object passed to the setupConfig function.
+ //
+ // Acceptable cell parameters defined in layout:
+ // 1. notselectable: boolean
+ // Whether this column is (and all the cells in it are) selectable.
+
+ // name: String
+ // plugin name
+ name: "selector",
+
+ // noClear: Boolean
+ // Not to clear rows selected by IndirectSelection.
+/*
+ // _config: null,
+ // _enabled: true,
+ // _selecting: {
+ // row: false,
+ // col: false,
+ // cell: false
+ // },
+ // _selected: {
+ // row: [],
+ // col: [],
+ // cell: []
+ // },
+ // _startPoint: {},
+ // _currentPoint: {},
+ // _lastAnchorPoint: {},
+ // _lastEndPoint: {},
+ // _lastSelectedAnchorPoint: {},
+ // _lastSelectedEndPoint: {},
+ // _keyboardSelect: {
+ // row: 0,
+ // col: 0,
+ // cell: 0
+ // },
+ // _curType: null,
+ // _lastType: null,
+ // _usingKeyboard: false,
+ // _toSelect: true,
+*/
+
+ constructor: function(grid, args){
+ this.grid = grid;
+ this._config = {
+ row: MULTI,
+ col: MULTI,
+ cell: MULTI
+ };
+ this.noClear = args && args.noClear;
+ this.setupConfig(args);
+ if(grid.selectionMode === "single"){
+ this._config.row = SINGLE;
+ }
+ this._enabled = true;
+ this._selecting = {};
+ this._selected = {
+ "col": [],
+ "row": [],
+ "cell": []
+ };
+ this._startPoint = {};
+ this._currentPoint = {};
+ this._lastAnchorPoint = {};
+ this._lastEndPoint = {};
+ this._lastSelectedAnchorPoint = {};
+ this._lastSelectedEndPoint = {};
+ this._keyboardSelect = {};
+ this._lastType = null;
+ this._selectedRowModified = {};
+ this._hacks();
+ this._initEvents();
+ this._initAreas();
+ this._mixinGrid();
+ },
+ destroy: function(){
+ this.inherited(arguments);
+ },
+ //------------public--------------------
+ setupConfig: function(config){
+ // summary:
+ // Set selection mode for row/col/cell.
+ // config: Object
+ // An object with the following structure (all properties are optional):
+ // {
+ // //Default is "multi", all other values are same as "multi".
+ // row: false|"disabled"|"single",
+ // col: false|"disabled"|"single",
+ // cell: false|"disabled"|"single"
+ // }
+ if(!config || !lang.isObject(config)){
+ return;
+ }
+ var types = ["row", "col", "cell"];
+ for(var type in config){
+ if(array.indexOf(types, type) >= 0){
+ if(!config[type] || config[type] == "disabled"){
+ this._config[type] = DISABLED;
+ }else if(config[type] == "single"){
+ this._config[type] = SINGLE;
+ }else{
+ this._config[type] = MULTI;
+ }
+ }
+ }
+
+ //Have to set mode to default grid selection.
+ var mode = ["none","single","extended"][this._config.row];
+ this.grid.selection.setMode(mode);
+ },
+ isSelected: function(type, rowIndex, colIndex){
+ // summary:
+ // Check whether a location (a cell, a column or a row) is selected.
+ // tag:
+ // public
+ // type: String
+ // "row" or "col" or "cell"
+ // rowIndex: Integer
+ // If type is "row" or "cell", this is the row index.
+ // If type if "col", this is the column index.
+ // colIndex: Integer?
+ // Only valid when type is "cell"
+ // return: Boolean
+ // true if selected, false if not. If cell is covered by a selected column, it's selected.
+ return this._isSelected(type, _createItem(type, rowIndex, colIndex));
+ },
+ toggleSelect: function(type, rowIndex, colIndex){
+ this._startSelect(type, _createItem(type, rowIndex, colIndex), this._config[type] === MULTI, false, false, !this.isSelected(type, rowIndex, colIndex));
+ this._endSelect(type);
+ },
+ select: function(type, rowIndex, colIndex){
+ // summary:
+ // Select a location (a cell, a column or a row).
+ // tag:
+ // public
+ // type: String
+ // "row" or "col" or "cell"
+ // rowIndex: Integer
+ // If type is "row" or "cell", this is the row index.
+ // If type if "col", this is the column index.
+ // colIndex: Integer?
+ // Only valid when type is "cell"
+ if(!this.isSelected(type, rowIndex, colIndex)){
+ this.toggleSelect(type, rowIndex, colIndex);
+ }
+ },
+ deselect: function(type, rowIndex, colIndex){
+ if(this.isSelected(type, rowIndex, colIndex)){
+ this.toggleSelect(type, rowIndex, colIndex);
+ }
+ },
+ selectRange: function(type, start, end, toSelect){
+ // summary:
+ // Select a continuous range (a block of cells, a set of continuous columns or rows)
+ // tag:
+ // public
+ // type: String
+ // "row" or "col" or "cell"
+ // start: Integer | Object
+ // If type is "row" or "col", this is the index of the starting row or column.
+ // If type if "cell", this is the left-top cell of the range.
+ // end: Integer | Object
+ // If type is "row" or "col", this is the index of the ending row or column.
+ // If type if "cell", this is the right-bottom cell of the range.
+ this.grid._selectingRange = true;
+ var startPoint = type == "cell" ? _createItem(type, start.row, start.col) : _createItem(type, start),
+ endPoint = type == "cell" ? _createItem(type, end.row, end.col) : _createItem(type, end);
+ this._startSelect(type, startPoint, false, false, false, toSelect);
+ this._highlight(type, endPoint, toSelect === undefined ? true : toSelect);
+ this._endSelect(type);
+ this.grid._selectingRange = false;
+ },
+ clear: function(type){
+ // summary:
+ // Clear all selections.
+ // tag:
+ // public
+ // type: String?
+ // "row" or "col" or "cell". If omitted, clear all.
+ this._clearSelection(type || "all");
+ },
+ isSelecting: function(type){
+ // summary:
+ // Check whether the user is currently selecting something.
+ // tag:
+ // public
+ // type: String
+ // "row" or "col" or "cell"
+ // return: Boolean
+ // true if is selection, false otherwise.
+ if(typeof type == "undefined"){
+ return this._selecting.col || this._selecting.row || this._selecting.cell;
+ }
+ return this._selecting[type];
+ },
+ selectEnabled: function(toEnable){
+ // summary:
+ // Turn on/off this selection functionality if *toEnable* is provided.
+ // Check whether this selection functionality is enabled if nothing is passed in.
+ // tag:
+ // public
+ // toEnable: Boolean?
+ // To enable or not. Optional.
+ // return: Boolean | undefined
+ // Enabled or not.
+ if(typeof toEnable != "undefined" && !this.isSelecting()){
+ this._enabled = !!toEnable;
+ }
+ return this._enabled;
+ },
+ getSelected: function(type, includeExceptions){
+ // summary:
+ // Get an array of selected locations.
+ // tag:
+ // public
+ // type: String
+ // "row" or "col" or "cell"
+ // includeExceptions: Boolean
+ // Only meaningful for rows/columns. If true, all selected rows/cols, even they are partly selected, are all returned.
+ // return: __SelectItem[]
+ switch(type){
+ case "cell":
+ return array.map(this._selected[type], function(item){ return item; });
+ case "col": case "row":
+ return array.map(includeExceptions ? this._selected[type]
+ : array.filter(this._selected[type], function(item){
+ return item.except.length === 0;
+ }), function(item){
+ return includeExceptions ? item : item[type];
+ });
+ }
+ return [];
+ },
+ getSelectedCount: function(type, includeExceptions){
+ // summary:
+ // Get the number of selected items.
+ // tag:
+ // public
+ // type: String
+ // "row" or "col" or "cell"
+ // includeExceptions: Boolean
+ // Only meaningful for rows/columns. If true, all selected rows/cols, even they are partly selected, are all returned.
+ // return: Integer
+ // The number of selected items.
+ switch(type){
+ case "cell":
+ return this._selected[type].length;
+ case "col": case "row":
+ return (includeExceptions ? this._selected[type]
+ : array.filter(this._selected[type], function(item){
+ return item.except.length === 0;
+ })).length;
+ }
+ return 0;
+ },
+ getSelectedType: function(){
+ // summary:
+ // Get the type of selected items.
+ // tag:
+ // public
+ // return: String
+ // "row" or "col" or "cell", or any mix of these (separator is | ).
+ var s = this._selected;
+ return ["", "cell", "row", "row|cell",
+ "col", "col|cell", "col|row", "col|row|cell"
+ ][(!!s.cell.length) | (!!s.row.length << 1) | (!!s.col.length << 2)];
+ },
+ getLastSelectedRange: function(type){
+ // summary:
+ // Get last selected range of the given type.
+ // tag:
+ // public
+ // return: Object
+ // {start: __SelectItem, end: __SelectItem}
+ // return null if nothing is selected.
+ return this._lastAnchorPoint[type] ? {
+ "start": this._lastAnchorPoint[type],
+ "end": this._lastEndPoint[type]
+ } : null;
+ },
+
+ //--------------------------private----------------------------
+ _hacks: function(){
+ // summary:
+ // Complete the event system of grid, hack some grid functions to prevent default behavior.
+ var g = this.grid;
+ var doContentMouseUp = function(e){
+ if(e.cellNode){
+ g.onMouseUp(e);
+ }
+ g.onMouseUpRow(e);
+ };
+ var mouseUp = lang.hitch(g, "onMouseUp");
+ var mouseDown = lang.hitch(g, "onMouseDown");
+ var doRowSelectorFocus = function(e){
+ e.cellNode.style.border = "solid 1px";
+ };
+ array.forEach(g.views.views, function(view){
+ view.content.domouseup = doContentMouseUp;
+ view.header.domouseup = mouseUp;
+ if(view.declaredClass == "dojox.grid._RowSelector"){
+ view.domousedown = mouseDown;
+ view.domouseup = mouseUp;
+ view.dofocus = doRowSelectorFocus;
+ }
+ });
+ //Disable default selection.
+ g.selection.clickSelect = function(){};
+
+ this._oldDeselectAll = g.selection.deselectAll;
+ var _this = this;
+ g.selection.selectRange = function(from, to){
+ _this.selectRange("row", from, to, true);
+ if(g.selection.preserver){
+ g.selection.preserver._updateMapping(true, true, false, from, to);
+ }
+ g.selection.onChanged();
+ };
+ g.selection.deselectRange = function(from, to){
+ _this.selectRange("row", from, to, false);
+ if(g.selection.preserver){
+ g.selection.preserver._updateMapping(true, false, false, from, to);
+ }
+ g.selection.onChanged();
+ };
+ g.selection.deselectAll = function(){
+ g._selectingRange = true;
+ _this._oldDeselectAll.apply(g.selection, arguments);
+ _this._clearSelection("all");
+ g._selectingRange = false;
+ if(g.selection.preserver){
+ g.selection.preserver._updateMapping(true, false, true);
+ }
+ g.selection.onChanged();
+ };
+
+ var rowSelector = g.views.views[0];
+ //The default function re-write the whole className, so can not insert any other classes.
+ if(rowSelector instanceof _RowSelector){
+ rowSelector.doStyleRowNode = function(inRowIndex, inRowNode){
+ html.removeClass(inRowNode, "dojoxGridRow");
+ html.addClass(inRowNode, "dojoxGridRowbar");
+ html.addClass(inRowNode, "dojoxGridNonNormalizedCell");
+ html.toggleClass(inRowNode, "dojoxGridRowbarOver", g.rows.isOver(inRowIndex));
+ html.toggleClass(inRowNode, "dojoxGridRowbarSelected", !!g.selection.isSelected(inRowIndex));
+ };
+ }
+ this.connect(g, "updateRow", function(rowIndex){
+ array.forEach(g.layout.cells, function(cell){
+ if(this.isSelected("cell", rowIndex, cell.index)){
+ this._highlightNode(cell.getNode(rowIndex), true);
+ }
+ }, this);
+ });
+ },
+ _mixinGrid: function(){
+ // summary:
+ // Expose events to grid.
+ var g = this.grid;
+ g.setupSelectorConfig = lang.hitch(this, this.setupConfig);
+ g.onStartSelect = function(){};
+ g.onEndSelect = function(){};
+ g.onStartDeselect = function(){};
+ g.onEndDeselect = function(){};
+ g.onSelectCleared = function(){};
+ },
+ _initEvents: function(){
+ // summary:
+ // Connect events, create event handlers.
+ var g = this.grid,
+ _this = this,
+ dp = lang.partial,
+ starter = function(type, e){
+ if(type === "row"){
+ _this._isUsingRowSelector = true;
+ }
+ //only left mouse button can select.
+ if(_this.selectEnabled() && _this._config[type] && e.button != 2){
+ if(_this._keyboardSelect.col || _this._keyboardSelect.row || _this._keyboardSelect.cell){
+ _this._endSelect("all");
+ _this._keyboardSelect.col = _this._keyboardSelect.row = _this._keyboardSelect.cell = 0;
+ }
+ if(_this._usingKeyboard){
+ _this._usingKeyboard = false;
+ }
+ var target = _createItem(type, e.rowIndex, e.cell && e.cell.index);
+ _this._startSelect(type, target, e.ctrlKey, e.shiftKey);
+ }
+ },
+ ender = lang.hitch(this, "_endSelect");
+ this.connect(g, "onHeaderCellMouseDown", dp(starter, "col"));
+ this.connect(g, "onHeaderCellMouseUp", dp(ender, "col"));
+
+ this.connect(g, "onRowSelectorMouseDown", dp(starter, "row"));
+ this.connect(g, "onRowSelectorMouseUp", dp(ender, "row"));
+
+ this.connect(g, "onCellMouseDown", function(e){
+ if(e.cell && e.cell.isRowSelector){ return; }
+ if(g.singleClickEdit){
+ _this._singleClickEdit = true;
+ g.singleClickEdit = false;
+ }
+ starter(_this._config["cell"] == DISABLED ? "row" : "cell", e);
+ });
+ this.connect(g, "onCellMouseUp", function(e){
+ if(_this._singleClickEdit){
+ delete _this._singleClickEdit;
+ g.singleClickEdit = true;
+ }
+ ender("all", e);
+ });
+
+ this.connect(g, "onCellMouseOver", function(e){
+ if(_this._curType != "row" && _this._selecting[_this._curType] && _this._config[_this._curType] == MULTI){
+ _this._highlight("col", _createItem("col", e.cell.index), _this._toSelect);
+ if(!_this._keyboardSelect.cell){
+ _this._highlight("cell", _createItem("cell", e.rowIndex, e.cell.index), _this._toSelect);
+ }
+ }
+ });
+ this.connect(g, "onHeaderCellMouseOver", function(e){
+ if(_this._selecting.col && _this._config.col == MULTI){
+ _this._highlight("col", _createItem("col", e.cell.index), _this._toSelect);
+ }
+ });
+ this.connect(g, "onRowMouseOver", function(e){
+ if(_this._selecting.row && _this._config.row == MULTI){
+ _this._highlight("row", _createItem("row", e.rowIndex), _this._toSelect);
+ }
+ });
+
+ //When row order has changed in a unpredictable way (sorted or filtered), map the new rowindex.
+ this.connect(g, "onSelectedById", "_onSelectedById");
+
+ //When the grid refreshes, all those selected should still appear selected.
+ this.connect(g, "_onFetchComplete", function(){
+ //console.debug("refresh after buildPage:", g._notRefreshSelection);
+ if(!g._notRefreshSelection){
+ this._refreshSelected(true);
+ }
+ });
+
+ //Small scroll might not refresh the grid.
+ this.connect(g.scroller, "buildPage", function(){
+ //console.debug("refresh after buildPage:", g._notRefreshSelection);
+ if(!g._notRefreshSelection){
+ this._refreshSelected(true);
+ }
+ });
+
+ //Whenever the mouse is up, end selecting.
+ this.connect(win.doc, "onmouseup", dp(ender, "all"));
+
+ //If autoscroll is enabled, connect to it.
+ this.connect(g, "onEndAutoScroll", function(isVertical, isForward, view, target){
+ var selectCell = _this._selecting.cell,
+ type, current, dir = isForward ? 1 : -1;
+ if(isVertical && (selectCell || _this._selecting.row)){
+ type = selectCell ? "cell" : "row";
+ current = _this._currentPoint[type];
+ _this._highlight(type, _createItem(type, current.row + dir, current.col), _this._toSelect);
+ }else if(!isVertical && (selectCell || _this._selecting.col)){
+ type = selectCell ? "cell" : "col";
+ current = _this._currentPoint[type];
+ _this._highlight(type, _createItem(type, current.row, target), _this._toSelect);
+ }
+ });
+ //If the grid is changed, selection should be consistent.
+ this.subscribe("dojox/grid/rearrange/move/" + g.id, "_onInternalRearrange");
+ this.subscribe("dojox/grid/rearrange/copy/" + g.id, "_onInternalRearrange");
+ this.subscribe("dojox/grid/rearrange/change/" + g.id, "_onExternalChange");
+ this.subscribe("dojox/grid/rearrange/insert/" + g.id, "_onExternalChange");
+ this.subscribe("dojox/grid/rearrange/remove/" + g.id, "clear");
+
+ //have to also select when the grid's default select is used.
+ this.connect(g, "onSelected", function(rowIndex){
+ if(this._selectedRowModified && this._isUsingRowSelector){
+ delete this._selectedRowModified;
+ }else if(!this.grid._selectingRange){
+ this.select("row", rowIndex);
+ }
+ });
+ this.connect(g, "onDeselected", function(rowIndex){
+ if(this._selectedRowModified && this._isUsingRowSelector){
+ delete this._selectedRowModified;
+ }else if(!this.grid._selectingRange){
+ this.deselect("row", rowIndex);
+ }
+ });
+ },
+ _onSelectedById: function(id, newIndex, isSelected){
+ if(this.grid._noInternalMapping){
+ return;
+ }
+ var pointSet = [this._lastAnchorPoint.row, this._lastEndPoint.row,
+ this._lastSelectedAnchorPoint.row, this._lastSelectedEndPoint.row];
+ pointSet = pointSet.concat(this._selected.row);
+ var found = false;
+ array.forEach(pointSet, function(item){
+ if(item){
+ if(item.id === id){
+ found = true;
+ item.row = newIndex;
+ }else if(item.row === newIndex && item.id){
+ item.row = -1;
+ }
+ }
+ });
+ if(!found && isSelected){
+ array.some(this._selected.row, function(item){
+ if(item && !item.id && !item.except.length){
+ item.id = id;
+ item.row = newIndex;
+ return true;
+ }
+ return false;
+ });
+ }
+ found = false;
+ pointSet = [this._lastAnchorPoint.cell, this._lastEndPoint.cell,
+ this._lastSelectedAnchorPoint.cell, this._lastSelectedEndPoint.cell];
+ pointSet = pointSet.concat(this._selected.cell);
+ array.forEach(pointSet, function(item){
+ if(item){
+ if(item.id === id){
+ found = true;
+ item.row = newIndex;
+ }else if(item.row === newIndex && item.id){
+ item.row = -1;
+ }
+ }
+ });
+ },
+ onSetStore: function(){
+ this._clearSelection("all");
+ },
+ _onInternalRearrange: function(type, mapping){
+ try{
+ //The column can not refresh it self!
+ this._refresh("col", false);
+
+ array.forEach(this._selected.row, function(item){
+ array.forEach(this.grid.layout.cells, function(cell){
+ this._highlightNode(cell.getNode(item.row), false);
+ }, this);
+ }, this);
+ //The rowbar must be cleaned manually
+ query(".dojoxGridRowSelectorSelected").forEach(function(node){
+ html.removeClass(node, "dojoxGridRowSelectorSelected");
+ html.removeClass(node, "dojoxGridRowSelectorSelectedUp");
+ html.removeClass(node, "dojoxGridRowSelectorSelectedDown");
+ });
+
+ var cleanUp = function(item){
+ if(item){
+ delete item.converted;
+ }
+ },
+ pointSet = [this._lastAnchorPoint[type], this._lastEndPoint[type],
+ this._lastSelectedAnchorPoint[type], this._lastSelectedEndPoint[type]];
+
+ if(type === "cell"){
+ this.selectRange("cell", mapping.to.min, mapping.to.max);
+ var cells = this.grid.layout.cells;
+ array.forEach(pointSet, function(item){
+ if(item.converted){ return; }
+ for(var r = mapping.from.min.row, tr = mapping.to.min.row; r <= mapping.from.max.row; ++r, ++tr){
+ for(var c = mapping.from.min.col, tc = mapping.to.min.col; c <= mapping.from.max.col; ++c, ++tc){
+ while(cells[c].hidden){ ++c; }
+ while(cells[tc].hidden){ ++tc; }
+ if(item.row == r && item.col == c){
+ //console.log('mapping found: (', item.row, ",",item.col,") to (", tr, ",", tc,")");
+ item.row = tr;
+ item.col = tc;
+ item.converted = true;
+ return;
+ }
+ }
+ }
+ });
+ }else{
+ pointSet = this._selected.cell.concat(this._selected[type]).concat(pointSet).concat(
+ [this._lastAnchorPoint.cell, this._lastEndPoint.cell,
+ this._lastSelectedAnchorPoint.cell, this._lastSelectedEndPoint.cell]);
+ array.forEach(pointSet, function(item){
+ if(item && !item.converted){
+ var from = item[type];
+ if(from in mapping){
+ item[type] = mapping[from];
+ }
+ item.converted = true;
+ }
+ });
+ array.forEach(this._selected[_theOther[type]], function(item){
+ for(var i = 0, len = item.except.length; i < len; ++i){
+ var from = item.except[i];
+ if(from in mapping){
+ item.except[i] = mapping[from];
+ }
+ }
+ });
+ }
+
+ array.forEach(pointSet, cleanUp);
+
+ this._refreshSelected(true);
+ this._focusPoint(type, this._lastEndPoint);
+ }catch(e){
+ console.warn("Selector._onInternalRearrange() error",e);
+ }
+ },
+ _onExternalChange: function(type, target){
+ var start = type == "cell" ? target.min : target[0],
+ end = type == "cell" ? target.max : target[target.length - 1];
+ this.selectRange(type, start, end);
+ },
+ _refresh: function(type, toHighlight){
+ if(!this._keyboardSelect[type]){
+ array.forEach(this._selected[type], function(item){
+ this._highlightSingle(type, toHighlight, item, undefined, true);
+ }, this);
+ }
+ },
+ _refreshSelected: function(){
+ this._refresh("col", true);
+ this._refresh("row", true);
+ this._refresh("cell", true);
+ },
+ _initAreas: function(){
+ var g = this.grid, f = g.focus, _this = this,
+ keyboardSelectReady = 1, duringKeyboardSelect = 2,
+ onmove = function(type, createNewEnd, rowStep, colStep, evt){
+ //Keyboard swipe selection is SHIFT + Direction Keys.
+ var ks = _this._keyboardSelect;
+ //Tricky, rely on valid status not being 0.
+ if(evt.shiftKey && ks[type]){
+ if(ks[type] === keyboardSelectReady){
+ if(type === "cell"){
+ var item = _this._lastEndPoint[type];
+ if(f.cell != g.layout.cells[item.col + colStep] || f.rowIndex != item.row + rowStep){
+ ks[type] = 0;
+ return;
+ }
+ }
+ //If selecting is not started, start it
+ _this._startSelect(type, _this._lastAnchorPoint[type], true, false, true);
+ _this._highlight(type, _this._lastEndPoint[type], _this._toSelect);
+ ks[type] = duringKeyboardSelect;
+ }
+ //Highlight to the new end point.
+ var newEnd = createNewEnd(type, rowStep, colStep, evt);
+ if(_this._isValid(type, newEnd, g)){
+ _this._highlight(type, newEnd, _this._toSelect);
+ }
+ _stopEvent(evt);
+ }
+ },
+ onkeydown = function(type, getTarget, evt, isBubble){
+ if(isBubble && _this.selectEnabled() && _this._config[type] != DISABLED){
+ switch(evt.keyCode){
+ case keys.SPACE:
+ //Keyboard single point selection is SPACE.
+ _this._startSelect(type, getTarget(), evt.ctrlKey, evt.shiftKey);
+ _this._endSelect(type);
+ break;
+ case keys.SHIFT:
+ //Keyboard swipe selection starts with SHIFT.
+ if(_this._config[type] == MULTI && _this._isValid(type, _this._lastAnchorPoint[type], g)){
+ //End last selection if any.
+ _this._endSelect(type);
+ _this._keyboardSelect[type] = keyboardSelectReady;
+ _this._usingKeyboard = true;
+ }
+ }
+ }
+ },
+ onkeyup = function(type, evt, isBubble){
+ if(isBubble && evt.keyCode == keys.SHIFT && _this._keyboardSelect[type]){
+ _this._endSelect(type);
+ _this._keyboardSelect[type] = 0;
+ }
+ };
+ //TODO: this area "rowHeader" should be put outside, same level as header/content.
+ if(g.views.views[0] instanceof _RowSelector){
+ this._lastFocusedRowBarIdx = 0;
+ f.addArea({
+ name:"rowHeader",
+ onFocus: function(evt, step){
+ var view = g.views.views[0];
+ if(view instanceof _RowSelector){
+ var rowBarNode = view.getCellNode(_this._lastFocusedRowBarIdx, 0);
+ if(rowBarNode){
+ html.toggleClass(rowBarNode, f.focusClass, false);
+ }
+ //evt might not be real event, it may be a mock object instead.
+ if(evt && "rowIndex" in evt){
+ if(evt.rowIndex >= 0){
+ _this._lastFocusedRowBarIdx = evt.rowIndex;
+ }else if(!_this._lastFocusedRowBarIdx){
+ _this._lastFocusedRowBarIdx = 0;
+ }
+ }
+ rowBarNode = view.getCellNode(_this._lastFocusedRowBarIdx, 0);
+ if(rowBarNode){
+ dijitFocus.focus(rowBarNode);
+ html.toggleClass(rowBarNode, f.focusClass, true);
+ }
+ f.rowIndex = _this._lastFocusedRowBarIdx;
+ _stopEvent(evt);
+ return true;
+ }
+ return false;
+ },
+ onBlur: function(evt, step){
+ var view = g.views.views[0];
+ if(view instanceof _RowSelector){
+ var rowBarNode = view.getCellNode(_this._lastFocusedRowBarIdx, 0);
+ if(rowBarNode){
+ html.toggleClass(rowBarNode, f.focusClass, false);
+ }
+ _stopEvent(evt);
+ }
+ return true;
+ },
+ onMove: function(rowStep, colStep, evt){
+ var view = g.views.views[0];
+ if(rowStep && view instanceof _RowSelector){
+ var next = _this._lastFocusedRowBarIdx + rowStep;
+ if(next >= 0 && next < g.rowCount){
+ //TODO: these logic require a better Scroller.
+ _stopEvent(evt);
+ var rowBarNode = view.getCellNode(_this._lastFocusedRowBarIdx, 0);
+ html.toggleClass(rowBarNode, f.focusClass, false);
+ //If the row is not fetched, fetch it.
+ var sc = g.scroller;
+ var lastPageRow = sc.getLastPageRow(sc.page);
+ var rc = g.rowCount - 1, row = Math.min(rc, next);
+ if(next > lastPageRow){
+ g.setScrollTop(g.scrollTop + sc.findScrollTop(row) - sc.findScrollTop(_this._lastFocusedRowBarIdx));
+ }
+ //Now we have fetched the row.
+ rowBarNode = view.getCellNode(next, 0);
+ dijitFocus.focus(rowBarNode);
+ html.toggleClass(rowBarNode, f.focusClass, true);
+ _this._lastFocusedRowBarIdx = next;
+ //If the row is out of view, scroll to it.
+ f.cell = rowBarNode;
+ f.cell.view = view;
+ f.cell.getNode = function(index){
+ return f.cell;
+ };
+ f.rowIndex = _this._lastFocusedRowBarIdx;
+ f.scrollIntoView();
+ f.cell = null;
+ }
+ }
+ }
+ });
+ f.placeArea("rowHeader","before","content");
+ }
+ //Support keyboard selection.
+ f.addArea({
+ name:"cellselect",
+ onMove: lang.partial(onmove, "cell", function(type, rowStep, colStep, evt){
+ var current = _this._currentPoint[type];
+ return _createItem("cell", current.row + rowStep, current.col + colStep);
+ }),
+ onKeyDown: lang.partial(onkeydown, "cell", function(){
+ return _createItem("cell", f.rowIndex, f.cell.index);
+ }),
+ onKeyUp: lang.partial(onkeyup, "cell")
+ });
+ f.placeArea("cellselect","below","content");
+ f.addArea({
+ name:"colselect",
+ onMove: lang.partial(onmove, "col", function(type, rowStep, colStep, evt){
+ var current = _this._currentPoint[type];
+ return _createItem("col", current.col + colStep);
+ }),
+ onKeyDown: lang.partial(onkeydown, "col", function(){
+ return _createItem("col", f.getHeaderIndex());
+ }),
+ onKeyUp: lang.partial(onkeyup, "col")
+ });
+ f.placeArea("colselect","below","header");
+ f.addArea({
+ name:"rowselect",
+ onMove: lang.partial(onmove, "row", function(type, rowStep, colStep, evt){
+ return _createItem("row", f.rowIndex);
+ }),
+ onKeyDown: lang.partial(onkeydown, "row", function(){
+ return _createItem("row", f.rowIndex);
+ }),
+ onKeyUp: lang.partial(onkeyup, "row")
+ });
+ f.placeArea("rowselect","below","rowHeader");
+ },
+ _clearSelection: function(type, reservedItem){
+ // summary:
+ // Clear selection for given type and fire events, but retain the highlight for *reservedItem*,
+ // thus avoid "flashing".
+ // tag:
+ // private
+ // type: String
+ // "row", "col", or "cell
+ // reservedItem: __SelectItem
+ // The item to retain highlight.
+ if(type == "all"){
+ this._clearSelection("cell", reservedItem);
+ this._clearSelection("col", reservedItem);
+ this._clearSelection("row", reservedItem);
+ return;
+ }
+ this._isUsingRowSelector = true;
+ array.forEach(this._selected[type], function(item){
+ if(!_isEqual(type, reservedItem, item)){
+ this._highlightSingle(type, false, item);
+ }
+ }, this);
+ this._blurPoint(type, this._currentPoint);
+ this._selecting[type] = false;
+ this._startPoint[type] = this._currentPoint[type] = null;
+ this._selected[type] = [];
+
+ //Have to also deselect default grid selection.
+ if(type == "row" && !this.grid._selectingRange){
+ this._oldDeselectAll.call(this.grid.selection);
+ this.grid.selection._selectedById = {};
+ }
+
+ //Fire events.
+ this.grid.onEndDeselect(type, null, null, this._selected);
+ this.grid.onSelectCleared(type);
+ },
+ _startSelect: function(type, start, extending, isRange, mandatarySelect, toSelect){
+ // summary:
+ // Start selection, setup start point and current point, fire events.
+ // tag:
+ // private
+ // type: String
+ // "row", "col", or "cell"
+ // extending: Boolean
+ // Whether this is a multi selection
+ // isRange: Boolean
+ // Whether this is a range selection (i.e. select from the last end point to this point)
+ // start: __SelectItem
+ // The start point
+ // mandatarySelect: Boolean
+ // If true, toSelect will be same as the original selection status.
+ if(!this._isValid(type, start)){
+ return;
+ }
+ var lastIsSelected = this._isSelected(type, this._lastEndPoint[type]),
+ isSelected = this._isSelected(type, start);
+
+ if(this.noClear && !extending){
+ this._toSelect = toSelect === undefined ? true : toSelect;
+ }else{
+ //If we are modifying the selection using keyboard, retain the old status.
+ this._toSelect = mandatarySelect ? isSelected : !isSelected;
+ }
+
+ //If CTRL is not pressed or it's SINGLE mode, this is a brand new selection.
+ if(!extending || (!isSelected && this._config[type] == SINGLE)){
+ this._clearSelection("col", start);
+ this._clearSelection("cell", start);
+ if(!this.noClear || (type === 'row' && this._config[type] == SINGLE)){
+ this._clearSelection('row', start);
+ }
+ this._toSelect = toSelect === undefined ? true : toSelect;
+ }
+
+ this._selecting[type] = true;
+ this._currentPoint[type] = null;
+
+ //We're holding SHIFT while clicking, it's a Click-Range selection.
+ if(isRange && this._lastType == type && lastIsSelected == this._toSelect && this._config[type] == MULTI){
+ if(type === "row"){
+ this._isUsingRowSelector = true;
+ }
+ this._startPoint[type] = this._lastEndPoint[type];
+ this._highlight(type, this._startPoint[type]);
+ this._isUsingRowSelector = false;
+ }else{
+ this._startPoint[type] = start;
+ }
+ //Now start selection
+ this._curType = type;
+ this._fireEvent("start", type);
+ this._isStartFocus = true;
+ this._isUsingRowSelector = true;
+ this._highlight(type, start, this._toSelect);
+ this._isStartFocus = false;
+ },
+ _endSelect: function(type){
+ // summary:
+ // End selection. Keep records, fire events and cleanup status.
+ // tag:
+ // private
+ // type: String
+ // "row", "col", or "cell"
+ if(type === "row"){
+ delete this._isUsingRowSelector;
+ }
+ if(type == "all"){
+ this._endSelect("col");
+ this._endSelect("row");
+ this._endSelect("cell");
+ }else if(this._selecting[type]){
+ this._addToSelected(type);
+ this._lastAnchorPoint[type] = this._startPoint[type];
+ this._lastEndPoint[type] = this._currentPoint[type];
+ if(this._toSelect){
+ this._lastSelectedAnchorPoint[type] = this._lastAnchorPoint[type];
+ this._lastSelectedEndPoint[type] = this._lastEndPoint[type];
+ }
+ this._startPoint[type] = this._currentPoint[type] = null;
+ this._selecting[type] = false;
+ this._lastType = type;
+ this._fireEvent("end", type);
+ }
+ },
+ _fireEvent: function(evtName, type){
+ switch(evtName){
+ case "start":
+ this.grid[this._toSelect ? "onStartSelect" : "onStartDeselect"](type, this._startPoint[type], this._selected);
+ break;
+ case "end":
+ this.grid[this._toSelect ? "onEndSelect" : "onEndDeselect"](type, this._lastAnchorPoint[type], this._lastEndPoint[type], this._selected);
+ break;
+ }
+ },
+ _calcToHighlight: function(type, target, toHighlight, toSelect){
+ // summary:
+ // Calculate what status should *target* have.
+ // If *toSelect* is not provided, this is a no op.
+ // This function is time-critical!!
+ if(toSelect !== undefined){
+ var sltd;
+ if(this._usingKeyboard && !toHighlight){
+ var last = this._isInLastRange(this._lastType, target);
+ if(last){
+ sltd = this._isSelected(type, target);
+ //This 2 cases makes the keyboard swipe selection valid!
+ if(toSelect && sltd){
+ return false;
+ }
+ if(!toSelect && !sltd && this._isInLastRange(this._lastType, target, true)){
+ return true;
+ }
+ }
+ }
+ return toHighlight ? toSelect : (sltd || this._isSelected(type, target));
+ }
+ return toHighlight;
+ },
+ _highlightNode: function(node, toHighlight){
+ // summary:
+ // Do the actual highlight work.
+ if(node){
+ var selectCSSClass = "dojoxGridRowSelected";
+ var selectCellClass = "dojoxGridCellSelected";
+ html.toggleClass(node, selectCSSClass, toHighlight);
+ html.toggleClass(node, selectCellClass, toHighlight);
+ }
+ },
+ _highlightHeader: function(colIdx, toHighlight){
+ var cells = this.grid.layout.cells;
+ var node = cells[colIdx].getHeaderNode();
+ var selectedClass = "dojoxGridHeaderSelected";
+ html.toggleClass(node, selectedClass, toHighlight);
+ },
+ _highlightRowSelector: function(rowIdx, toHighlight){
+ //var t1 = (new Date()).getTime();
+ var rowSelector = this.grid.views.views[0];
+ if(rowSelector instanceof _RowSelector){
+ var node = rowSelector.getRowNode(rowIdx);
+ if(node){
+ var selectedClass = "dojoxGridRowSelectorSelected";
+ html.toggleClass(node, selectedClass, toHighlight);
+ }
+ }
+ //console.log((new Date()).getTime() - t1);
+ },
+ _highlightSingle: function(type, toHighlight, target, toSelect, isRefresh){
+ // summary:
+ // Highlight a single item.
+ // This function is time critical!!
+ var _this = this, toHL, g = _this.grid, cells = g.layout.cells;
+ switch(type){
+ case "cell":
+ toHL = this._calcToHighlight(type, target, toHighlight, toSelect);
+ var c = cells[target.col];
+ if(!c.hidden && !c.notselectable){
+ this._highlightNode(target.node || c.getNode(target.row), toHL);
+ }
+ break;
+ case "col":
+ toHL = this._calcToHighlight(type, target, toHighlight, toSelect);
+ this._highlightHeader(target.col, toHL);
+ query("td[idx='" + target.col + "']", g.domNode).forEach(function(cellNode){
+ var rowNode = cells[target.col].view.content.findRowTarget(cellNode);
+ if(rowNode){
+ var rowIndex = rowNode[dojox.grid.util.rowIndexTag];
+ _this._highlightSingle("cell", toHL, {
+ "row": rowIndex,
+ "col": target.col,
+ "node": cellNode
+ });
+ }
+ });
+ break;
+ case "row":
+ toHL = this._calcToHighlight(type, target, toHighlight, toSelect);
+ this._highlightRowSelector(target.row, toHL);
+ if(this._config.cell){
+ array.forEach(cells, function(cell){
+ _this._highlightSingle("cell", toHL, {
+ "row": target.row,
+ "col": cell.index,
+ "node": cell.getNode(target.row)
+ });
+ });
+ }
+ //To avoid dead lock
+ this._selectedRowModified = true;
+ if(!isRefresh){
+ g.selection.setSelected(target.row, toHL);
+ }
+ }
+ },
+ _highlight: function(type, target, toSelect){
+ // summary:
+ // Highlight from start point to target.
+ // toSelect: Boolean
+ // Whether we are selecting or deselecting.
+ // This function is time critical!!
+ if(this._selecting[type] && target !== null){
+ var start = this._startPoint[type],
+ current = this._currentPoint[type],
+ _this = this,
+ highlight = function(from, to, toHL){
+ _this._forEach(type, from, to, function(item){
+ _this._highlightSingle(type, toHL, item, toSelect);
+ }, true);
+ };
+ switch(type){
+ case "col": case "row":
+ if(current !== null){
+ if(_inRange(type, target, start, current, true)){
+ //target is between start and current, some selected should be deselected.
+ highlight(current, target, false);
+ }else{
+ if(_inRange(type, start, target, current, true)){
+ //selection has jumped to different direction, all should be deselected.
+ highlight(current, start, false);
+ current = start;
+ }
+ highlight(target, current, true);
+ }
+ }else{
+ //First time select.
+ this._highlightSingle(type, true, target, toSelect);
+ }
+ break;
+ case "cell":
+ if(current !== null){
+ if(_inRange("row", target, start, current, true) ||
+ _inRange("col", target, start, current, true) ||
+ _inRange("row", start, target, current, true) ||
+ _inRange("col", start, target, current, true)){
+ highlight(start, current, false);
+ }
+ }
+ highlight(start, target, true);
+ }
+ this._currentPoint[type] = target;
+ this._focusPoint(type, this._currentPoint);
+ }
+ },
+ _focusPoint: function(type, point){
+ // summary:
+ // Focus the current point, so when you move mouse, the focus indicator follows you.
+ if(!this._isStartFocus){
+ var current = point[type],
+ f = this.grid.focus;
+ if(type == "col"){
+ f._colHeadFocusIdx = current.col;
+ f.focusArea("header");
+ }else if(type == "row"){
+ f.focusArea("rowHeader", {
+ "rowIndex": current.row
+ });
+ }else if(type == "cell"){
+ f.setFocusIndex(current.row, current.col);
+ }
+ }
+ },
+ _blurPoint: function(type, point){
+ // summary:
+ // Blur the current point.
+ var f = this.grid.focus;
+ if(type == "col"){
+ f._blurHeader();
+ }else if(type == "cell"){
+ f._blurContent();
+ }
+ },
+ _addToSelected: function(type){
+ // summary:
+ // Record the selected items.
+ var toSelect = this._toSelect, _this = this,
+ toAdd = [], toRemove = [],
+ start = this._startPoint[type],
+ end = this._currentPoint[type];
+ if(this._usingKeyboard){
+ //If using keyboard, selection will be ended after every move. But we have to remember the original selection status,
+ //so as to return to correct status when we shrink the selection region.
+ this._forEach(type, this._lastAnchorPoint[type], this._lastEndPoint[type], function(item){
+ //If the original selected item is not in current range, change its status.
+ if(!_inRange(type, item, start, end)){
+ (toSelect ? toRemove : toAdd).push(item);
+ }
+ });
+ }
+ this._forEach(type, start, end, function(item){
+ var isSelected = _this._isSelected(type, item);
+ if(toSelect && !isSelected){
+ //Add new selected items
+ toAdd.push(item);
+ }else if(!toSelect){
+ //Remove deselected items.
+ toRemove.push(item);
+ }
+ });
+ this._add(type, toAdd);
+ this._remove(type, toRemove);
+
+ // have to keep record in original grid selection
+ array.forEach(this._selected.row, function(item){
+ if(item.except.length > 0){
+ //to avoid dead lock
+ this._selectedRowModified = true;
+ this.grid.selection.setSelected(item.row, false);
+ }
+ }, this);
+ },
+ _forEach: function(type, start, end, func, halfClose){
+ // summary:
+ // Go through items from *start* point to *end* point.
+ // This function is time critical!!
+ if(!this._isValid(type, start, true) || !this._isValid(type, end, true)){
+ return;
+ }
+ switch(type){
+ case "col": case "row":
+ start = start[type];
+ end = end[type];
+ var dir = end > start ? 1 : -1;
+ if(!halfClose){
+ end += dir;
+ }
+ for(; start != end; start += dir){
+ func(_createItem(type, start));
+ }
+ break;
+ case "cell":
+ var colDir = end.col > start.col ? 1 : -1,
+ rowDir = end.row > start.row ? 1 : -1;
+ for(var i = start.row, p = end.row + rowDir; i != p; i += rowDir){
+ for(var j = start.col, q = end.col + colDir; j != q; j += colDir){
+ func(_createItem(type, i, j));
+ }
+ }
+ }
+ },
+ _makeupForExceptions: function(type, newCellItems){
+ // summary:
+ // When new cells is selected, maybe they will fill in the "holes" in selected rows and columns.
+ var makedUps = [];
+ array.forEach(this._selected[type], function(v1){
+ array.forEach(newCellItems, function(v2){
+ if(v1[type] == v2[type]){
+ var pos = array.indexOf(v1.except, v2[_theOther[type]]);
+ if(pos >= 0){
+ v1.except.splice(pos, 1);
+ }
+ makedUps.push(v2);
+ }
+ });
+ });
+ return makedUps;
+ },
+ _makeupForCells: function(type, newItems){
+ // summary:
+ // When some rows/cols are selected, maybe they can cover some of the selected cells,
+ // and fill some of the "holes" in the selected cols/rows.
+ var toRemove = [];
+ array.forEach(this._selected.cell, function(v1){
+ array.some(newItems, function(v2){
+ if(v1[type] == v2[type]){
+ toRemove.push(v1);
+ return true;
+ }
+ return false;
+ });
+ });
+ this._remove("cell", toRemove);
+ array.forEach(this._selected[_theOther[type]], function(v1){
+ array.forEach(newItems, function(v2){
+ var pos = array.indexOf(v1.except, v2[type]);
+ if(pos >= 0){
+ v1.except.splice(pos, 1);
+ }
+ });
+ });
+ },
+ _addException: function(type, items){
+ // summary:
+ // If some rows/cols are deselected, maybe they have created "holes" in selected cols/rows.
+ array.forEach(this._selected[type], function(v1){
+ array.forEach(items, function(v2){
+ v1.except.push(v2[_theOther[type]]);
+ });
+ });
+ },
+ _addCellException: function(type, items){
+ // summary:
+ // If some cells are deselected, maybe they have created "holes" in selected rows/cols.
+ array.forEach(this._selected[type], function(v1){
+ array.forEach(items, function(v2){
+ if(v1[type] == v2[type]){
+ v1.except.push(v2[_theOther[type]]);
+ }
+ });
+ });
+ },
+ _add: function(type, items){
+ // summary:
+ // Add to the selection record.
+ var cells = this.grid.layout.cells;
+ if(type == "cell"){
+ var colMakedup = this._makeupForExceptions("col", items);
+ var rowMakedup = this._makeupForExceptions("row", items);
+ //Step over hidden columns.
+ items = array.filter(items, function(item){
+ return array.indexOf(colMakedup, item) < 0 && array.indexOf(rowMakedup, item) < 0 &&
+ !cells[item.col].hidden && !cells[item.col].notselectable;
+ });
+ }else{
+ if(type == "col"){
+ //Step over hidden columns.
+ items = array.filter(items, function(item){
+ return !cells[item.col].hidden && !cells[item.col].notselectable;
+ });
+ }
+ this._makeupForCells(type, items);
+ this._selected[type] = array.filter(this._selected[type], function(v){
+ return array.every(items, function(item){
+ return v[type] !== item[type];
+ });
+ });
+ }
+ if(type != "col" && this.grid._hasIdentity){
+ array.forEach(items, function(item){
+ var record = this.grid._by_idx[item.row];
+ if(record){
+ item.id = record.idty;
+ }
+ }, this);
+ }
+ this._selected[type] = this._selected[type].concat(items);
+ },
+ _remove: function(type, items){
+ // summary:
+ // Remove from the selection record.
+ var comp = lang.partial(_isEqual, type);
+ this._selected[type] = array.filter(this._selected[type], function(v1){
+ return !array.some(items, function(v2){
+ return comp(v1, v2);
+ });
+ });
+ if(type == "cell"){
+ this._addCellException("col", items);
+ this._addCellException("row", items);
+ }else if(this._config.cell){
+ this._addException(_theOther[type], items);
+ }
+ },
+ _isCellNotInExcept: function(type, item){
+ // summary:
+ // Return true only when a cell is covered by selected row/col, and its not a "hole".
+ var attr = item[type], corres = item[_theOther[type]];
+ return array.some(this._selected[type], function(v){
+ return v[type] == attr && array.indexOf(v.except, corres) < 0;
+ });
+ },
+ _isSelected: function(type, item){
+ // summary:
+ // Return true when the item is selected. (or logically selected, i.e, covered by a row/col).
+ if(!item){ return false; }
+ var res = array.some(this._selected[type], function(v){
+ var ret = _isEqual(type, item, v);
+ if(ret && type !== "cell"){
+ return v.except.length === 0;
+ }
+ return ret;
+ });
+ if(!res && type === "cell"){
+ res = (this._isCellNotInExcept("col", item) || this._isCellNotInExcept("row", item));
+ if(type === "cell"){
+ res = res && !this.grid.layout.cells[item.col].notselectable;
+ }
+ }
+ return res;
+ },
+ _isInLastRange: function(type, item, isSelected){
+ // summary:
+ // Return true only when the item is in the last seletion/deseletion range.
+ var start = this[isSelected ? "_lastSelectedAnchorPoint" : "_lastAnchorPoint"][type],
+ end = this[isSelected ? "_lastSelectedEndPoint" : "_lastEndPoint"][type];
+ if(!item || !start || !end){ return false; }
+ return _inRange(type, item, start, end);
+ },
+ _isValid: function(type, item, allowNotSelectable){
+ // summary:
+ // Check whether the item is a valid __SelectItem for the given type.
+ if(!item){ return false; }
+ try{
+ var g = this.grid, index = item[type];
+ switch(type){
+ case "col":
+ return index >= 0 && index < g.layout.cells.length && lang.isArray(item.except) &&
+ (allowNotSelectable || !g.layout.cells[index].notselectable);
+ case "row":
+ return index >= 0 && index < g.rowCount && lang.isArray(item.except);
+ case "cell":
+ return item.col >= 0 && item.col < g.layout.cells.length &&
+ item.row >= 0 && item.row < g.rowCount &&
+ (allowNotSelectable || !g.layout.cells[item.col].notselectable);
+ }
+ }catch(e){}
+ return false;
+ }
+});
+
+EnhancedGrid.registerPlugin(Selector/*name:'selector'*/, {
+ "dependency": ["autoScroll"]
+});
+
+return Selector;
+
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/plugins/_RowMapLayer.js b/js/dojo/dojox/grid/enhanced/plugins/_RowMapLayer.js
new file mode 100644
index 0000000..bf19ce3
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/_RowMapLayer.js
@@ -0,0 +1,207 @@
+//>>built
+define("dojox/grid/enhanced/plugins/_RowMapLayer", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/lang",
+ "./_StoreLayer"
+], function(declare, array, lang, layers){
+
+var _devideToArrays = function(a){
+ a.sort(function(v1, v2){
+ return v1 - v2;
+ });
+ var arr = [[a[0]]];
+ for(var i = 1, j = 0; i < a.length; ++i){
+ if(a[i] == a[i-1] + 1){
+ arr[j].push(a[i]);
+ }else{
+ arr[++j] = [a[i]];
+ }
+ }
+ return arr;
+},
+hitchIfCan = function(scope, func){
+ return func ? lang.hitch(scope || lang.global, func) : function(){};
+};
+
+return declare("dojox.grid.enhanced.plugins._RowMapLayer", layers._StoreLayer, {
+ tags: ["reorder"],
+ constructor: function(grid){
+ this._map = {};
+ this._revMap = {};
+ this.grid = grid;
+ this._oldOnDelete = grid._onDelete;
+ var _this = this;
+ grid._onDelete = function(item){
+ _this._onDelete(item);
+ _this._oldOnDelete.call(grid, item);
+ };
+ this._oldSort = grid.sort;
+ grid.sort = function(){
+ _this.clearMapping();
+ _this._oldSort.apply(grid, arguments);
+ };
+ },
+ uninitialize: function(){
+ this.grid._onDelete = this._oldOnDelete;
+ this.grid.sort = this._oldSort;
+ },
+ setMapping: function(mapping){
+ // summary:
+ // Remember the row mapping.
+ // mapping: Object
+ // keys are original rowIndexes, values are new rowIndexes.
+ this._store.forEachLayer(function(layer){
+ if(layer.name() === "rowmap"){
+ return false;
+ }else if(layer.onRowMappingChange){
+ layer.onRowMappingChange(mapping);
+ }
+ return true;
+ }, false);
+ var from, to, origin, revmap = {};
+ for(from in mapping){
+ from = parseInt(from, 10);
+ to = mapping[from];
+ if(typeof to == "number"){
+ if(from in this._revMap){
+ origin = this._revMap[from];
+ delete this._revMap[from];
+ }else{
+ origin = from;
+ }
+ if(origin == to){
+ delete this._map[origin];
+ revmap[to] = "eq";
+ }else{
+ this._map[origin] = to;
+ revmap[to] = origin;
+ }
+ }
+ }
+ for(to in revmap){
+ if(revmap[to] === "eq"){
+ delete this._revMap[parseInt(to, 10)];
+ }else{
+ this._revMap[parseInt(to, 10)] = revmap[to];
+ }
+ }
+ },
+ clearMapping: function(){
+ this._map = {};
+ this._revMap = {};
+ },
+ _onDelete: function(item){
+ var idx = this.grid._getItemIndex(item, true);
+ if(idx in this._revMap){
+ var rowIdxArr = [], r, i, origin = this._revMap[idx];
+ delete this._map[origin];
+ delete this._revMap[idx];
+ for(r in this._revMap){
+ r = parseInt(r, 10);
+ if(this._revMap[r] > origin){
+ --this._revMap[r];
+ }
+ }
+ for(r in this._revMap){
+ r = parseInt(r, 10);
+ if(r > idx){
+ rowIdxArr.push(r);
+ }
+ }
+ rowIdxArr.sort(function(a, b){
+ return b - a;
+ });
+ for(i = rowIdxArr.length - 1; i >= 0; --i){
+ r = rowIdxArr[i];
+ this._revMap[r - 1] = this._revMap[r];
+ delete this._revMap[r];
+ }
+ this._map = {};
+ for(r in this._revMap){
+ this._map[this._revMap[r]] = r;
+ }
+ }
+ },
+ _fetch: function(userRequest){
+ var mapCount = 0, r;
+ var start = userRequest.start || 0;
+ for(r in this._revMap){
+ r = parseInt(r, 10);
+ if(r >= start){
+ ++mapCount;
+ }
+ }
+ if(mapCount > 0){
+ //Row mapping is in use.
+ var rows = [], i, map = {},
+ count = userRequest.count > 0 ? userRequest.count : -1;
+ if(count > 0){
+ for(i = 0; i < count; ++i){
+ r = start + i;
+ r = r in this._revMap ? this._revMap[r] : r;
+ map[r] = i;
+ rows.push(r);
+ }
+ }else{
+ //We don't have a count, must create our own.
+ for(i = 0;; ++i){
+ r = start + i;
+ if(r in this._revMap){
+ --mapCount;
+ r = this._revMap[r];
+ }
+ map[r] = i;
+ rows.push(r);
+ if(mapCount <= 0){
+ break;
+ }
+ }
+ }
+ this._subFetch(userRequest, this._getRowArrays(rows), 0, [], map, userRequest.onComplete, start, count);
+ return userRequest;
+ }else{
+ //No row mapping at all.
+ return lang.hitch(this._store, this._originFetch)(userRequest);
+ }
+ },
+ _getRowArrays: function(rows){
+ return _devideToArrays(rows);
+ },
+ _subFetch: function(userRequest, rowArrays, index, result, map, oldOnComplete, start, count){
+ var arr = rowArrays[index], _this = this;
+ var urstart = userRequest.start = arr[0];
+ userRequest.count = arr[arr.length - 1] - arr[0] + 1;
+ userRequest.onComplete = function(items){
+ array.forEach(items, function(item, i){
+ var r = urstart + i;
+ if(r in map){
+ result[map[r]] = item;
+ }
+ });
+ if(++index == rowArrays.length){
+ //mapped rows are all fetched.
+ if(count > 0){
+ userRequest.start = start;
+ userRequest.count = count;
+ userRequest.onComplete = oldOnComplete;
+ hitchIfCan(userRequest.scope, oldOnComplete)(result, userRequest);
+ }else{
+ userRequest.start = userRequest.start + items.length;
+ delete userRequest.count;
+ userRequest.onComplete = function(items){
+ result = result.concat(items);
+ userRequest.start = start;
+ userRequest.onComplete = oldOnComplete;
+ hitchIfCan(userRequest.scope, oldOnComplete)(result, userRequest);
+ };
+ _this.originFetch(userRequest);
+ }
+ }else{
+ _this._subFetch(userRequest, rowArrays, index, result, map, oldOnComplete, start, count);
+ }
+ };
+ _this.originFetch(userRequest);
+ }
+});
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/_SelectionPreserver.js b/js/dojo/dojox/grid/enhanced/plugins/_SelectionPreserver.js
new file mode 100644
index 0000000..dff96c1
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/_SelectionPreserver.js
@@ -0,0 +1,109 @@
+//>>built
+define("dojox/grid/enhanced/plugins/_SelectionPreserver", [
+ "dojo/_base/declare",
+ "dojo/_base/lang",
+ "dojo/_base/connect",
+ '../../_SelectionPreserver'
+], function(declare, lang, connect, _SelectionPreserver){
+
+return declare("dojox.grid.enhanced.plugins._SelectionPreserver", _SelectionPreserver, {
+ // summary:
+ // Preserve selections across various user actions.
+ //
+ // description:
+ // Extends dojox.grid._SelectionPreserver adding a bit more support to make selection persistence working well
+ // with various EnhancedGrid features, e.g. filtering, nested sorting, pagination, select all etc.
+ //
+ // Precondition - Identifier(id) is required for store, as id is used for differentiating row items.
+ // Known issue - The preserved selections might be inaccurate if some unloaded rows are previously selected by range(e.g.SHIFT + click)
+ //
+ // example:
+ // | //To turn on this - set 'keepSelection' attribute to true
+ // | <div dojoType="dojox.grid.EnhancedGrid" keepSelection = true .../>
+
+ constructor: function(selection){
+ var grid = this.grid;
+ grid.onSelectedById = this.onSelectedById;
+ this._oldClearData = grid._clearData;
+ var self = this;
+ grid._clearData = function(){
+ self._updateMapping(!grid._noInternalMapping);
+ self._trustSelection = [];
+ self._oldClearData.apply(grid, arguments);
+ };
+ this._connects.push(
+ connect.connect(selection, 'selectRange', lang.hitch(this, '_updateMapping', true, true, false)),
+ connect.connect(selection, 'deselectRange', lang.hitch(this, '_updateMapping', true, false, false)),
+ connect.connect(selection, 'deselectAll', lang.hitch(this, '_updateMapping', true, false, true))
+ );
+ },
+ destroy: function(){
+ this.inherited(arguments);
+ this.grid._clearData = this._oldClearData;
+ },
+ reset: function(){
+ this.inherited(arguments);
+ this._idMap = [];
+ this._trustSelection = [];
+ this._defaultSelected = false;
+ },
+ _reSelectById: function(item, index){
+ // summary:
+ // Overwritten
+ var s = this.selection, g = this.grid;
+ if(item && g._hasIdentity){
+ var id = g.store.getIdentity(item);
+ if(this._selectedById[id] === undefined){
+ if(!this._trustSelection[index]){
+ s.selected[index] = this._defaultSelected;
+ }
+ }else{
+ s.selected[index] = this._selectedById[id];
+ }
+ this._idMap.push(id);
+ g.onSelectedById(id, index, s.selected[index]);
+ }
+ },
+ _selectById: function(toSelect, inItemOrIndex){
+ // summary:
+ // Overwritten
+ if(!this.inherited(arguments)){
+ this._trustSelection[inItemOrIndex] = true;
+ }
+ },
+ onSelectedById: function(id, rowIndex, value){},
+
+ _updateMapping: function(trustSelection, isSelect, isForAll, from, to){
+ // summary:
+ // This function try to keep the selection info updated when range selection is performed.
+ // 1. Calculate how many unloaded rows are there;
+ // 2. update _selectedById data if grid.selection._selected can be trusted, so loaded but unselected rows can
+ // be properly recorded.
+ var s = this.selection, g = this.grid, flag = 0, unloaded = 0, i, id;
+ for(i = g.rowCount - 1; i >= 0; --i){
+ if(!g._by_idx[i]){
+ ++unloaded;
+ flag += s.selected[i] ? 1 : -1;
+ }else{
+ id = g._by_idx[i].idty;
+ if(id && (trustSelection || this._selectedById[id] === undefined)){
+ this._selectedById[id] = !!s.selected[i];
+ }
+ }
+ }
+ if(unloaded){
+ this._defaultSelected = flag > 0;
+ }
+ if(!isForAll && from !== undefined && to !== undefined){
+ isForAll = !g.usingPagination && Math.abs(to - from + 1) === g.rowCount;
+ }
+ // When deselectAll, make sure every thing is deselected, even if it was selected but not loaded now.
+ // This occurs only when pagination's "All" is used.
+ if(isForAll && (!g.usingPagination || g.selectionMode === 'single')){
+ for(i = this._idMap.length - 1; i >= 0; --i){
+ this._selectedById[this._idMap[i]] = isSelect;
+ }
+ }
+ }
+});
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/_StoreLayer.js b/js/dojo/dojox/grid/enhanced/plugins/_StoreLayer.js
new file mode 100644
index 0000000..bf73a6d
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/_StoreLayer.js
@@ -0,0 +1,395 @@
+//>>built
+define("dojox/grid/enhanced/plugins/_StoreLayer", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/lang",
+ "dojo/_base/xhr"
+], function(declare, array, lang, xhr){
+// summary:
+// The dojo.data.api.Read API is powerful, but it's difficult to give the store some special commands before
+// fetch, so that the store content can be temporarily modified or transformed, and acts as another store. The
+// parameter *query* or *queryOptions* in keywordArgs for *fetch* is not enough because:
+// 1. users do not have the opportunity to response to the store actions when these options or queries are applied,
+// especially when the real store is at server side.
+// 2. the store implementation must be changed to support any new options in 'query' or 'queryOptions', so it'll be
+// difficult if this implementation is not able to or very hard to be changed, or some new options are required to
+// be valid for all stores.
+// This *StoreLayer* framework is dedicated to provide a uniform way for configuring an existing store, so that
+// it can be easily extended to have special behaviors or act like a totally different store.
+// The major approach is to wrap the *fetch* function of store, layer by layer. Every layer treats the incoming
+// store.fetch as a 'black box', thus maintaining the independence between layers.
+// *fetch* is the most important data retriever in the Read API, almost all other functions are used for a single
+// item, and require that this item is already retrieved (by and only by *fetch*). So once we've controlled this
+// *fetch* function, we've controlled almost the whole store. This fact simplifies our implementation of StoreLayer.
+// example:
+// //ns is for namespace, i.e.:dojox.grid.enhanced.plugins
+// ns.wrap(ns.wrap(ns.wrap(store, new ns.FilterLayer()), new ns.UniqueLayer()), new ns.TransformLayer());
+//
+// //every layer has a name, it should be given in the document of this layer.
+// //if you don't know it's name, you can get it by: ns.SomeLayer.prototype.name();
+// store.layer("filter").filterDef(...);
+// store.layer("unique").setUniqueColumns(...);
+// store.layer("transform").setScheme(...);
+//
+// //now use the store as usual...
+//
+// store.unwrap("transform"); //remove the transform layer but retain the other two.
+//
+// //now use the store as usual...
+//
+// store.unwrap(); //remove all the layers, get the original store back.
+
+ var ns = lang.getObject("grid.enhanced.plugins", true, dojox);
+
+ var getPrevTags = function(tags){
+ var tagList = ["reorder", "sizeChange", "normal", "presentation"];
+ var idx = tagList.length;
+ for(var i = tags.length - 1; i >= 0; --i){
+ var p = array.indexOf(tagList, tags[i]);
+ if(p >= 0 && p <= idx){
+ idx = p;
+ }
+ }
+ if(idx < tagList.length - 1){
+ return tagList.slice(0, idx + 1);
+ }else{
+ return tagList;
+ }
+ },
+
+ unwrap = function(/* string? */layerName){
+ // summary:
+ // Unwrap the layers of the store
+ // tags:
+ // public
+ // returns:
+ // The unwrapped store, for nested use only.
+ var i, layers = this._layers, len = layers.length;
+ if(layerName){
+ for(i = len-1; i >= 0; --i){
+ if(layers[i].name() == layerName){
+ layers[i]._unwrap(layers[i + 1]);
+ break;
+ }
+ }
+ layers.splice(i, 1);
+ }else{
+ for(i = len - 1; i >= 0; --i){
+ layers[i]._unwrap();
+ }
+ }
+ if(!layers.length){
+ delete this._layers;
+ delete this.layer;
+ delete this.unwrap;
+ delete this.forEachLayer;
+ }
+ //console.log("layers:",this._layers);
+ return this; //Read-store
+ },
+
+ getLayer = function(layerName){
+ // summary:
+ // Get a layer of the store, so we can configure that layer.
+ // tags:
+ // public (scope is store)
+ // layerName: string
+ // the name of the layer
+ // returns:
+ // the store layer object
+ var i, layers = this._layers;
+ if(typeof layerName == "undefined"){
+ return layers.length; //Integer
+ }
+ if(typeof layerName == "number"){
+ return layers[layerName]; //_StoreLayer
+ }
+ for(i = layers.length - 1; i >= 0; --i){
+ if(layers[i].name() == layerName){
+ return layers[i]; //_StoreLayer
+ }
+ }
+ return null; //_StoreLayer
+ },
+
+ forEachLayer = function(callback, isInnerToOuter){
+ // summary:
+ // Visit the layers one by one. From the outer most to inner most by default.
+ // callback: Function
+ // The function to callback.
+ // If return false, break the loop.
+ // isInnerToOuter: Boolean
+ // Whether visit from the inner most layer to the outer most layer.
+ var len = this._layers.length, start, end, dir;
+ if(isInnerToOuter){
+ start = 0;
+ end = len;
+ dir = 1;
+ }else{
+ start = len - 1;
+ end = -1;
+ dir = -1;
+ }
+ for(var i = start; i != end; i += dir){
+ if(callback(this._layers[i], i) === false){
+ return i;
+ }
+ }
+ return end;
+ };
+ ns.wrap = function(store, funcName, layer, layerFuncName){
+ // summary:
+ // Wrap the store with the given layer.
+ // tags:
+ // public
+ // store: Read-store
+ // The store to be wrapped.
+ // layer: _StoreLayer
+ // The layer to be used
+ // returns
+ // The wrapped store, for nested use only.
+ if(!store._layers){
+ store._layers = [];
+ store.layer = lang.hitch(store, getLayer);
+ store.unwrap = lang.hitch(store, unwrap);
+ store.forEachLayer = lang.hitch(store, forEachLayer);
+ }
+ var prevTags = getPrevTags(layer.tags);
+ if(!array.some(store._layers, function(lyr, i){
+ if(array.some(lyr.tags, function(tag){
+ return array.indexOf(prevTags, tag) >= 0;
+ })){
+ return false;
+ }else{
+ store._layers.splice(i, 0, layer);
+ layer._wrap(store, funcName, layerFuncName, lyr);
+ return true;
+ }
+ })){
+ store._layers.push(layer);
+ layer._wrap(store, funcName, layerFuncName);
+ }
+ //console.log("wrapped layers:", dojo.map(store._layers, function(lyr){return lyr.name();}));
+ return store; //Read-store
+ };
+
+ var _StoreLayer = declare("dojox.grid.enhanced.plugins._StoreLayer", null, {
+ // summary:
+ // The most abstract class of store layers, provides basic utilities and some interfaces.
+ // tags:
+ // abstract
+/*=====
+ // _store: [protected] Read-store
+ // The wrapped store.
+ _store: null,
+
+ // _originFetch: [protected] function
+ // The original fetch function of the store.
+ _originFetch: null,
+
+ // __enabled: [private] Boolean
+ // To control whether this layer is valid.
+ __enabled: true,
+=====*/
+ tags: ["normal"],
+
+ layerFuncName: "_fetch",
+
+ constructor: function(){
+ this._store = null;
+ this._originFetch = null;
+ this.__enabled = true;
+ },
+ initialize: function(store){
+ // summary:
+ //
+ },
+ uninitialize: function(store){
+ // summary:
+ //
+ },
+ invalidate: function(){
+
+ },
+ _wrap: function(store, funcName, layerFuncName, nextLayer){
+ // summary:
+ // Do the actual wrapping (or 'hacking' if you like) to the store.
+ // tags:
+ // internal
+ // store: Read-store
+ // The store to be wrapped.
+ this._store = store;
+ this._funcName = funcName;
+ var fetchFunc = lang.hitch(this, function(){
+ return (this.enabled() ? this[layerFuncName || this.layerFuncName] : this.originFetch).apply(this, arguments);
+ });
+ if(nextLayer){
+ this._originFetch = nextLayer._originFetch;
+ nextLayer._originFetch = fetchFunc;
+ }else{
+ this._originFetch = store[funcName] || function(){};
+ store[funcName] = fetchFunc;
+ }
+ this.initialize(store);
+ },
+ _unwrap: function(nextLayer){
+ // summary:
+ // Do the actual unwrapping to the store.
+ // tags:
+ // internal
+ // store: Read-store
+ // The store to be unwrapped.
+ this.uninitialize(this._store);
+ if(nextLayer){
+ nextLayer._originFetch = this._originFetch;
+ }else{
+ this._store[this._funcName] = this._originFetch;
+ }
+ this._originFetch = null;
+ this._store = null;
+ },
+ enabled: function(/* bool? */toEnable){
+ // summary:
+ // The get/set function of the enabled status of this layer
+ // tags:
+ // public
+ // toEnable: Boolean?
+ // If given, is a setter, otherwise, it's getter.
+ if(typeof toEnable != "undefined"){
+ this.__enabled = !!toEnable;
+ }
+ return this.__enabled; //Boolean
+ },
+ name: function(){
+ // summary:
+ // Get the name of this store layer.
+ // The default name retrieved from class name, which should have a pattern of "{name}Layer".
+ // If this pattern does not exist, the whole class name will be this layer's name.
+ // It's better to override this method if your class name is too complicated.
+ // tags:
+ // public extension
+ // returns:
+ // The name of this layer.
+ if(!this.__name){
+ var m = this.declaredClass.match(/(?:\.(?:_*)([^\.]+)Layer$)|(?:\.([^\.]+)$)/i);
+ this.__name = m ? (m[1] || m[2]).toLowerCase() : this.declaredClass;
+ }
+ return this.__name;
+ },
+ originFetch: function(){
+ return (lang.hitch(this._store, this._originFetch)).apply(this, arguments);
+ }
+ });
+ var _ServerSideLayer = declare("dojox.grid.enhanced.plugins._ServerSideLayer", _StoreLayer, {
+ // summary:
+ // The most abstract class for all server side store layers.
+ // tags:
+ // abstract
+/*=====
+ // _url: [protected] string
+ // The url of the server
+ _url: "",
+ // __cmds [private] object
+ // The command object to be sent to server.
+ __cmds: {},
+=====*/
+ constructor: function(args){
+ args = args || {};
+ this._url = args.url || "";
+ this._isStateful = !!args.isStateful;
+ this._onUserCommandLoad = args.onCommandLoad || function(){};
+ this.__cmds = {cmdlayer:this.name(), enable:true};
+
+ //Only for stateful server, sending commands before fetch makes sense.
+ this.useCommands(this._isStateful);
+ },
+ enabled: function(/* bool? */toEnable){
+ // summary:
+ // Overrided from _StoreLayer.enabled
+ var res = this.inherited(arguments);
+ this.__cmds.enable = this.__enabled;
+ return res;
+ },
+ useCommands: function(/* bool? */toUse){
+ // summary:
+ // If you only want to modify the user request, instead of sending a separate command
+ // to server before fetch, just call:
+ // this.useCommand(false);
+ // tags:
+ // public
+ // toUse: Boolean?
+ // If provided, it's a setter, otherwise, it's a getter
+ if(typeof toUse != "undefined"){
+ this.__cmds.cmdlayer = (toUse && this._isStateful) ? this.name() : null;
+ }
+ return !!(this.__cmds.cmdlayer); //Boolean
+ },
+ _fetch: function(/* keywordArgs */userRequest){
+ // summary:
+ // Implementation of _StoreLayer._fetch
+ if(this.__cmds.cmdlayer){
+ //We're gonna send command to server before fetch.
+ xhr.post({
+ url: this._url || this._store.url,
+ content: this.__cmds,
+ load: lang.hitch(this, function(responce){
+ this.onCommandLoad(responce, userRequest);
+ this.originFetch(userRequest);
+ }),
+ error: lang.hitch(this, this.onCommandError)
+ });
+ }else{
+ //The user only wants to modify the request object.
+ this.onCommandLoad("", userRequest);
+ this.originFetch(userRequest);
+ }
+ return userRequest; //dojo.data.api.Request
+ },
+ command: function(/* string */cmdName,/* (string|number|bool|...)? */cmdContent){
+ // summary:
+ // get/set a command (a name-value pair)
+ // tags:
+ // public
+ // cmdName: string
+ // The name of the command
+ // cmdContent: anything
+ // The content of the command
+ // returns:
+ // The content of the command if cmdContent is undefined
+ var cmds = this.__cmds;
+ if(cmdContent === null){
+ delete cmds[cmdName];
+ }else if(typeof cmdContent !== "undefined"){
+ cmds[cmdName] = cmdContent;
+ }
+ return cmds[cmdName]; //anything
+ },
+ onCommandLoad: function(/* string */response, /* keywordArgs */userRequest){
+ // summary:
+ // When the server gives back *response* for the commands, you can do something here.
+ // tags:
+ // callback extension
+ // response: string
+ // server response
+ // userRequest: [in|out] dojo.data.api.Request
+ // The request object for *fetch*. You can modify this object according to the *response*
+ // so as to change the behavior of *fetch*
+ this._onUserCommandLoad(this.__cmds, userRequest, response);
+ },
+ onCommandError: function(error){
+ // summary:
+ // handle errors when sending commands.
+ // tags:
+ // callback extension
+ // error: Error
+ console.log(error);
+ throw error;
+ }
+ });
+
+ return {
+ _StoreLayer: _StoreLayer,
+ _ServerSideLayer: _ServerSideLayer,
+ wrap: ns.wrap
+ };
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/exporter/CSVWriter.js b/js/dojo/dojox/grid/enhanced/plugins/exporter/CSVWriter.js
new file mode 100644
index 0000000..44006e2
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/exporter/CSVWriter.js
@@ -0,0 +1,88 @@
+//>>built
+define("dojox/grid/enhanced/plugins/exporter/CSVWriter", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "./_ExportWriter",
+ "../Exporter"
+], function(declare, array, _ExportWriter, Exporter){
+
+Exporter.registerWriter("csv", "dojox.grid.enhanced.plugins.exporter.CSVWriter");
+
+return declare("dojox.grid.enhanced.plugins.exporter.CSVWriter", _ExportWriter, {
+ // summary:
+ // Export grid to CSV format.
+ _separator: ',',
+
+ _newline: "\r\n",
+
+ constructor: function(/* object? */writerArgs){
+ // summary:
+ // CSV default separator is ','.
+ // But we can also use our own.
+ // writerArgs: object?
+ // {separator:'...'}
+ if(writerArgs){
+ this._separator = writerArgs.separator ? writerArgs.separator : this._separator;
+ this._newline = writerArgs.newline ? writerArgs.newline : this._newline;
+ }
+ this._headers = [];
+ this._dataRows = [];
+ },
+
+ _formatCSVCell: function(/* string */cellValue){
+ // summary:
+ // Format cell value to follow CSV standard.
+ // See: http://en.wikipedia.org/wiki/Comma-separated_values
+ // tags:
+ // private
+ // cellValue: string
+ // The value in a cell.
+ // returns:
+ // The formatted content of a cell
+ if(cellValue === null || cellValue === undefined){
+ return '';
+ }
+ var result = String(cellValue).replace(/"/g, '""');
+ if(result.indexOf(this._separator) >= 0 || result.search(/[" \t\r\n]/) >= 0){
+ result = '"' + result + '"';
+ }
+ return result; //String
+ },
+
+ beforeContentRow: function(/* object */arg_obj){
+ // summary:
+ // Overrided from _ExportWriter
+ var row = [],
+ func = this._formatCSVCell;
+ array.forEach(arg_obj.grid.layout.cells, function(cell){
+ //We are not interested in indirect selectors and row indexes.
+ if(!cell.hidden && array.indexOf(arg_obj.spCols,cell.index) < 0){
+ //We only need data here, not html
+ row.push(func(this._getExportDataForCell(arg_obj.rowIndex, arg_obj.row, cell, arg_obj.grid)));
+ }
+ }, this);
+ this._dataRows.push(row);
+ //We do not need to go into the row.
+ return false; //Boolean
+ },
+
+ handleCell: function(/* object */arg_obj){
+ // summary:
+ // Overrided from _ExportWriter
+ var cell = arg_obj.cell;
+ if(arg_obj.isHeader && !cell.hidden && array.indexOf(arg_obj.spCols,cell.index) < 0){
+ this._headers.push(cell.name || cell.field);
+ }
+ },
+
+ toString: function(){
+ // summary:
+ // Overrided from _ExportWriter
+ var result = this._headers.join(this._separator);
+ for(var i = this._dataRows.length - 1; i >= 0; --i){
+ this._dataRows[i] = this._dataRows[i].join(this._separator);
+ }
+ return result + this._newline + this._dataRows.join(this._newline); //String
+ }
+});
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/exporter/TableWriter.js b/js/dojo/dojox/grid/enhanced/plugins/exporter/TableWriter.js
new file mode 100644
index 0000000..0ea2c74
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/exporter/TableWriter.js
@@ -0,0 +1,160 @@
+//>>built
+define("dojox/grid/enhanced/plugins/exporter/TableWriter", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/dom-geometry",
+ "./_ExportWriter",
+ "../Exporter"
+], function(declare, array, domGeometry, _ExportWriter, Exporter){
+
+Exporter.registerWriter("table", "dojox.grid.enhanced.plugins.exporter.TableWriter");
+
+return declare("dojox.grid.enhanced.plugins.exporter.TableWriter", _ExportWriter, {
+ // summary:
+ // Export grid to HTML table format. Primarily used by Printer plugin.
+ constructor: function(/* object? */writerArgs){
+ // summary:
+ // The generated table only defines the col/rowspan, height and width of
+ // all the cells in the style attribute, no other attributes
+ // (like border, cellspacing, etc.) are used.
+ // Users can define these attributes in the writerArgs object, like:
+ // {table:"border='border'",thead:"cellspacing='3'"}
+ this._viewTables = [];
+ this._tableAttrs = writerArgs || {};
+ },
+
+ _getTableAttrs: function(/* string */tagName){
+ // summary:
+ // Get html attribute string for the given kind of tag.
+ // tags:
+ // private
+ // tagName: string
+ // An html tag name
+ // returns:
+ // The well formatted attributes for the given html table.tag
+ var attrs = this._tableAttrs[tagName] || '';
+ //To ensure the attribute list starts with a space
+ if(attrs && attrs[0] != ' '){
+ attrs = ' ' + attrs;
+ }
+ return attrs; //String
+ },
+
+ _getRowClass: function(/* object */arg_obj){
+ // summary:
+ // Get CSS class string for a row
+ // tags:
+ // private
+ return arg_obj.isHeader ? " grid_header" : [//String
+ " grid_row grid_row_",
+ arg_obj.rowIdx + 1,
+ arg_obj.rowIdx % 2 ? " grid_even_row" : " grid_odd_row"
+ ].join('');
+ },
+
+ _getColumnClass: function(/* object */arg_obj){
+ // summary:
+ // Get CSS class string for a column
+ // tags:
+ // private
+ var col_idx = arg_obj.cell.index + arg_obj.colOffset + 1;
+ return [" grid_column grid_column_", col_idx,//String
+ col_idx % 2 ? " grid_odd_column" : " grid_even_column"].join('');
+ },
+
+ beforeView: function(/* object */arg_obj){
+ // summary:
+ // Overrided from _ExportWriter
+ var viewIdx = arg_obj.viewIdx,
+ table = this._viewTables[viewIdx],
+ height, width = domGeometry.getMarginBox(arg_obj.view.contentNode).w;
+ if(!table){
+ var left = 0;
+ for(var i = 0; i < viewIdx; ++i){
+ left += this._viewTables[i]._width;
+ }
+ table = this._viewTables[viewIdx] = ['<div class="grid_view" style="position: absolute; top: 0; ',
+ domGeometry.isBodyLtr() ? 'left' : 'right', ':', left,
+ 'px;">'];
+ }
+ table._width = width;
+ if(arg_obj.isHeader){
+ height = domGeometry.getContentBox(arg_obj.view.headerContentNode).h;
+ }else{
+ var rowNode = arg_obj.grid.getRowNode(arg_obj.rowIdx);
+ if(rowNode){
+ height = domGeometry.getContentBox(rowNode).h;
+ }else{
+ //This row has not been loaded from store, so we should estimate it's height.
+ height = arg_obj.grid.scroller.averageRowHeight;
+ }
+ }
+ table.push('<table class="', this._getRowClass(arg_obj),
+ '" style="table-layout:fixed; height:', height, 'px; width:', width, 'px;" ',
+ 'border="0" cellspacing="0" cellpadding="0" ',
+ this._getTableAttrs("table"),
+ '><tbody ', this._getTableAttrs('tbody'), '>');
+ return true; //Boolean
+ },
+
+ afterView: function(/* object */arg_obj){
+ // summary:
+ // Overrided from _ExportWriter
+ this._viewTables[arg_obj.viewIdx].push('</tbody></table>');
+ },
+
+ beforeSubrow: function(/* object */arg_obj){
+ // summary:
+ // Overrided from _ExportWriter
+ this._viewTables[arg_obj.viewIdx].push('<tr', this._getTableAttrs('tr'), '>');
+ return true; //Boolean
+ },
+
+ afterSubrow: function(/* object */arg_obj){
+ // summary:
+ // Overrided from _ExportWriter
+ this._viewTables[arg_obj.viewIdx].push('</tr>');
+ },
+
+ handleCell: function(/* object */arg_obj){
+ // summary:
+ // Overrided from _ExportWriter
+ var cell = arg_obj.cell;
+ if(cell.hidden || array.indexOf(arg_obj.spCols, cell.index) >= 0){
+ //We are not interested in indirect selectors and row indexes.
+ return;
+ }
+ var cellTagName = arg_obj.isHeader ? 'th' : 'td',
+ attrs = [cell.colSpan ? ' colspan="' + cell.colSpan + '"' : '',
+ cell.rowSpan ? ' rowspan="' + cell.rowSpan + '"' : '',
+ ' style="width: ', domGeometry.getContentBox(cell.getHeaderNode()).w, 'px;"',
+ this._getTableAttrs(cellTagName),
+ ' class="', this._getColumnClass(arg_obj), '"'].join(''),
+ table = this._viewTables[arg_obj.viewIdx];
+ table.push('<', cellTagName, attrs, '>');
+ if(arg_obj.isHeader){
+ table.push(cell.name || cell.field);
+ } else{
+ table.push(this._getExportDataForCell(arg_obj.rowIdx, arg_obj.row, cell, arg_obj.grid));
+ }
+ table.push('</', cellTagName, '>');
+ },
+
+ afterContent: function(){
+ // summary:
+ // Overrided from _ExportWriter
+ array.forEach(this._viewTables, function(table){
+ table.push('</div>');
+ });
+ },
+
+ toString: function(){
+ // summary:
+ // Overrided from _ExportWriter
+ var viewsHTML = array.map(this._viewTables, function(table){ //String
+ return table.join('');
+ }).join('');
+ return ['<div style="position: relative;">', viewsHTML, '</div>'].join('');
+ }
+});
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/exporter/_ExportWriter.js b/js/dojo/dojox/grid/enhanced/plugins/exporter/_ExportWriter.js
new file mode 100644
index 0000000..14bd39f
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/exporter/_ExportWriter.js
@@ -0,0 +1,269 @@
+//>>built
+define("dojox/grid/enhanced/plugins/exporter/_ExportWriter", [
+ "dojo/_base/declare"
+], function(declare){
+//require Exporter here, so the implementations only need to require this file,
+//and the users only need to require the implementation file.
+
+return declare("dojox.grid.enhanced.plugins.exporter._ExportWriter", null, {
+ // summary:
+ // This is an abstract class for all kinds of writers used in the Exporter plugin.
+ // It utilizes the strategy pattern to break the export work into several stages,
+ // and provide interfaces for all of them.
+ // Implementations might choose some of the functions in this class to override,
+ // thus providing their own functionalities.
+ // The Exporter will go through the grid line by line. So in every line, all the Views
+ // will be reached, and the header line is only handled once.
+ // An *argObj* object is passed to most functions of this class.
+ // It carries context arguments that make sense when they are called.
+
+/*=====
+ argObj: {
+ // grid: EnhancedGrid
+ // The grid object we are now handling.
+ grid: null,
+
+ // isHeader: bool
+ // Indicating which context we're handling, header or content.
+ isHeader: true,
+
+ // view: _View
+ // Reference to the current _View object.
+ view: null,
+
+ // viewIdx: int
+ // The index of the current _View object in the views array.
+ // If the grid does not have any rowselector view, it conforms to the index
+ // in the _ViewManager.views.
+ viewIdx: -1,
+
+ // subrow: _View.structure.cells[i]
+ // Reference to the current subrow.
+ // A subrow describe the innter structure of a row in a view, it's an array of cells
+ subrow: null,
+
+ // subrowIdx: int
+ // The index of the current subrow in the subrow array: _View.structure.cells.
+ subrowIdx: -1,
+
+ // cell: dojox.grid.__CellDef
+ // Reference to the current cell.
+ cell: null,
+
+ //cellIdx: int
+ // The index of the current cell in the current subrow.
+ // It's different from cell.index, which is the index in the whole line.
+ cellIdx: -1,
+
+ //row: item
+ // The current row of data (logically), a.k.a.: current item.
+ row: null,
+
+ //rowIdx: int
+ // The index of the current row (item).
+ rowIdx: -1,
+
+ // spCols: Array<int>
+ // An array of special column indexes(flat,not regarding structure).
+ // Special columns are typically attached to grid as a kind of UI facility
+ // by the grid widget, instead of some real data.
+ // For example, indirect selectors and row indexers.
+ // Users can choose to export it or not.
+ spCols: [],
+
+ // colOffset: int
+ // If the grid has a _RowSelector view or something else, this view will NOT be
+ // passed to the user in argObj. So the column index (cell.index) will appear shifted
+ // (start from 1 instead of 0). This colOffset is provided to remove this shift.
+ // usage:
+ // var correctColIndex = argObj.cell.index + argObj.colOffset;
+ colOffset: 0
+ },
+=====*/
+
+ constructor: function(/* object? */writerArgs){
+ // summary:
+ // Writer initializations goes here.
+ // writerArgs: object?
+ // Any implementation of this class might accept a writerArgs object (optional),
+ // which contains some writer-specific arguments given by the user.
+ },
+ _getExportDataForCell: function(rowIndex, rowItem, cell, grid){
+ var data = (cell.get || grid.get).call(cell, rowIndex, rowItem);
+ if(this.formatter){
+ return this.formatter(data, cell, rowIndex, rowItem);
+ }else{
+ return data;
+ }
+ },
+ beforeHeader: function(/* EnhancedGrid */grid){
+ // summary:
+ // We are going to start the travel in the grid.
+ // Is there anything we should do now?
+ // tags:
+ // protected extension
+ // return:
+ // true: go on hanling the header row and then call afterHeader.
+ // false: skip the header row, won't call afterHeader.
+ return true; //Boolean
+ },
+ afterHeader: function(){
+ // summary:
+ // The header line has been handled.
+ // tags:
+ // protected extension
+ // returns:
+ // undefined
+ },
+ beforeContent: function(/* Array */items){
+ // summary:
+ // We are ready to go through all the contents(items).
+ // tags:
+ // protected extension
+ // items:
+ // All the items fetched from the store
+ // return:
+ // true: go on handling the contents and then call afterContent.
+ // false: skip all the contents, won't call afterContent.
+ return true; //Boolean
+ },
+ afterContent: function(){
+ // summary:
+ // We have finished the entire grid travel.
+ // Do some clean up work if you need to.
+ // tags:
+ // protected extension
+ // returns:
+ // undefined
+ },
+ beforeContentRow: function(/* object */argObj){
+ // summary:
+ // Before handling a line of data (not header).
+ // tags:
+ // protected extension
+ // argObj:
+ // An object with at least the following context properties available:
+ // {
+ // grid,isHeader,
+ // row,rowIdx,
+ // spCols
+ // }
+ // return:
+ // true: go on handling the current data row and then call afterContentRow.
+ // false: skip the current data row, won't call afterContentRow.
+ return true; //Boolean
+ },
+ afterContentRow: function(/* object */argObj){
+ // summary:
+ // After handling a line of data (not header).
+ // tags:
+ // protected extension
+ // argObj:
+ // An object with at least the following context properties available:
+ // {
+ // grid,isHeader,
+ // row,rowIdx,
+ // spCols
+ // }
+ // returns:
+ // undefined
+ },
+ beforeView: function(/* object */argObj){
+ // summary:
+ // Before handling a view.
+ // tags:
+ // protected extension
+ // argObj:
+ // An object with at least the following context properties available:
+ // {
+ // grid,isHeader,
+ // view,viewIdx,
+ // spCols(if isHeader==false)
+ // }
+ // return:
+ // true: go on handling the current view and then call afterView.
+ // false: skip the current view, won't call afterView.
+ return true; //Boolean
+ },
+ afterView: function(/* object */argObj){
+ // summary:
+ // After handling a view.
+ // tags:
+ // protected extension
+ // argObj:
+ // An object with at least the following context properties available:
+ // {
+ // grid,isHeader,
+ // view,viewIdx,
+ // spCols(if isHeader==false)
+ // }
+ // tags:
+ // protected extension
+ // returns:
+ // undefined
+ },
+ beforeSubrow: function(/* object */argObj){
+ // summary:
+ // Before handling a subrow in a line (defined in the grid structure).
+ // tags:
+ // protected extension
+ // argObj:
+ // An object with at least the following context properties available:
+ // {
+ // grid,isHeader,
+ // row,rowIdx,
+ // view,viewIdx,
+ // subrow,subrowIdx,
+ // spCols(if isHeader==false)
+ // }
+ // return:
+ // true: go on handling the current subrow and then call afterSubrow.
+ // false: skip the current subrow, won't call afterSubrow.
+ return true; //Boolean
+ },
+ afterSubrow: function(/* object */argObj){
+ // summary:
+ // Before handling a subrow in a line (defined in the grid structure).
+ // tags:
+ // protected extension
+ // argObj:
+ // An object with at least the following context properties available:
+ // {
+ // grid,isHeader,
+ // row,rowIdx,
+ // view,viewIdx,
+ // subrow,subrowIdx,
+ // spCols(if isHeader==false)
+ // }
+ // returns:
+ // undefined
+ },
+ handleCell: function(/* object */argObj){
+ // summary:
+ // Handle a header cell or data cell.
+ // tags:
+ // protected extension
+ // argObj:
+ // An object with at least the following context properties available:
+ // {
+ // grid,isHeader,
+ // row,rowIdx,
+ // view,viewIdx,
+ // subrow,subrowIdx,
+ // cell,cellIdx,
+ // spCols(if isHeader==false)
+ // }
+ // returns:
+ // undefined
+ },
+ toString: function(){
+ // summary:
+ // Export to a string.
+ // tags:
+ // protected extension
+ // returns:
+ // The exported result string.
+ return ''; //String
+ }
+});
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/filter/ClearFilterConfirm.js b/js/dojo/dojox/grid/enhanced/plugins/filter/ClearFilterConfirm.js
new file mode 100644
index 0000000..2a63dcb
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/filter/ClearFilterConfirm.js
@@ -0,0 +1,46 @@
+//>>built
+define("dojox/grid/enhanced/plugins/filter/ClearFilterConfirm", [
+ "dojo/_base/declare",
+ "dojo/cache",
+ "dijit/_Widget",
+ "dijit/_TemplatedMixin",
+ "dijit/_WidgetsInTemplateMixin"
+], function(declare, cache, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin){
+
+return declare("dojox.grid.enhanced.plugins.filter.ClearFilterConfirm",
+ [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin], {
+ // summary:
+ // The UI for user to confirm the operation of clearing filter.
+ templateString: cache("dojox.grid", "enhanced/templates/ClearFilterConfirmPane.html"),
+
+ widgetsInTemplate: true,
+
+ plugin: null,
+
+ postMixInProperties: function(){
+ var nls = this.plugin.nls;
+ this._clearBtnLabel = nls["clearButton"];
+ this._cancelBtnLabel = nls["cancelButton"];
+ this._clearFilterMsg = nls["clearFilterMsg"];
+ },
+
+ postCreate: function(){
+ this.inherited(arguments);
+ this.cancelBtn.domNode.setAttribute("aria-label", this.plugin.nls["waiCancelButton"]);
+ this.clearBtn.domNode.setAttribute("aria-label", this.plugin.nls["waiClearButton"]);
+ },
+
+ uninitialize: function(){
+ this.plugin = null;
+ },
+
+ _onCancel: function(){
+ this.plugin.clearFilterDialog.hide();
+ },
+
+ _onClear: function(){
+ this.plugin.clearFilterDialog.hide();
+ this.plugin.filterDefDialog.clearFilter(this.plugin.filterDefDialog._clearWithoutRefresh);
+ }
+});
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/filter/FilterBar.js b/js/dojo/dojox/grid/enhanced/plugins/filter/FilterBar.js
new file mode 100644
index 0000000..422c56a
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/filter/FilterBar.js
@@ -0,0 +1,386 @@
+//>>built
+define("dojox/grid/enhanced/plugins/filter/FilterBar", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "dojo/_base/lang",
+ "dojo/_base/sniff",
+ "dojo/_base/event",
+ "dojo/_base/html",
+ "dojo/_base/window",
+ "dojo/cache",
+ "dojo/query",
+ "dijit/_Widget",
+ "dijit/_TemplatedMixin",
+ "dijit/_WidgetsInTemplateMixin",
+ "dojo/fx",
+ "dojo/_base/fx",
+ "dojo/string",
+ "dijit/focus"
+], function(declare, array, connect, lang, has, event, html, win, cache, query, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, fx, baseFx, string, dijitFocus){
+
+var _focusClass = "dojoxGridFBarHover",
+ _filteredClass = "dojoxGridFBarFiltered",
+ _stopEvent = function(evt){
+ try{
+ if(evt && evt.preventDefault){
+ event.stop(evt);
+ }
+ }catch(e){}
+ };
+
+return declare("dojox.grid.enhanced.plugins.filter.FilterBar", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin],{
+ // summary:
+ // The filter bar UI.
+ templateString: cache("dojox.grid","enhanced/templates/FilterBar.html"),
+
+ widgetsInTemplate: true,
+
+ _timeout_statusTooltip: 300,
+
+ _handle_statusTooltip: null,
+
+ _curColIdx: -1,
+
+ plugin: null,
+
+ postMixInProperties: function(){
+ var plugin = this.plugin;
+ var nls = plugin.nls;
+ this._filterBarDefBtnLabel = nls["filterBarDefButton"];
+ this._filterBarClearBtnLabel = nls["filterBarClearButton"];
+ this._closeFilterBarBtnLabel = nls["closeFilterBarBtn"];
+ var itemsName = plugin.args.itemsName || nls["defaultItemsName"];
+ this._noFilterMsg = string.substitute(nls["filterBarMsgNoFilterTemplate"], ["", itemsName]);
+
+ var t = this.plugin.args.statusTipTimeout;
+ if(typeof t == 'number'){
+ this._timeout_statusTooltip = t;
+ }
+
+ var g = plugin.grid;
+ g.showFilterBar = lang.hitch(this, "showFilterBar");
+ g.toggleFilterBar = lang.hitch(this, "toggleFilterBar");
+ g.isFilterBarShown = lang.hitch(this, "isFilterBarShown");
+ },
+ postCreate: function(){
+ this.inherited(arguments);
+ if(!this.plugin.args.closeFilterbarButton){
+ html.style(this.closeFilterBarButton.domNode, "display", "none");
+ }
+ var _this = this,
+ g = this.plugin.grid,
+ old_func = this.oldGetHeaderHeight = lang.hitch(g,g._getHeaderHeight);
+
+ this.placeAt(g.viewsHeaderNode, "after");
+ this.connect(this.plugin.filterDefDialog, "showDialog", "_onShowFilterDefDialog");
+ this.connect(this.plugin.filterDefDialog, "closeDialog", "_onCloseFilterDefDialog");
+ this.connect(g.layer("filter"), "onFiltered", this._onFiltered);
+
+ this.defineFilterButton.domNode.title = this.plugin.nls["filterBarDefButton"];
+ if(html.hasClass(win.body(), "dijit_a11y")){
+ this.defineFilterButton.set("label", this.plugin.nls["a11yFilterBarDefButton"]);
+ }
+ this.connect(this.defineFilterButton.domNode, "click", _stopEvent);
+ this.connect(this.clearFilterButton.domNode, "click", _stopEvent);
+ this.connect(this.closeFilterBarButton.domNode, "click", _stopEvent);
+
+ this.toggleClearFilterBtn(true);
+ this._initAriaInfo();
+
+ //Hack the header height to include filter bar height;
+ g._getHeaderHeight = function(){
+ return old_func() + html.marginBox(_this.domNode).h;
+ };
+ //Define an area to make focusManager handle all the navigation stuff
+ g.focus.addArea({
+ name: "filterbar",
+ onFocus: lang.hitch(this, this._onFocusFilterBar, false),
+ onBlur: lang.hitch(this, this._onBlurFilterBar)
+ });
+ g.focus.placeArea("filterbar","after","header");
+ },
+ uninitialize: function(){
+ var g = this.plugin.grid;
+ g._getHeaderHeight = this.oldGetHeaderHeight;
+ g.focus.removeArea("filterbar");
+ this.plugin = null;
+ },
+ isFilterBarShown: function(){
+ return html.style(this.domNode, "display") != "none";
+ },
+ showFilterBar: function(toShow, useAnim, animArgs){
+ var g = this.plugin.grid;
+ if(useAnim){
+ if(Boolean(toShow) == this.isFilterBarShown()){ return; }
+ animArgs = animArgs || {};
+ var anims = [], defaultDuration = 500;
+ anims.push(fx[toShow ? "wipeIn" : "wipeOut"](lang.mixin({
+ "node": this.domNode,
+ "duration": defaultDuration
+ }, animArgs)));
+ var curHeight = g.views.views[0].domNode.offsetHeight;
+ var prop = {
+ "duration": defaultDuration,
+ "properties": {
+ "height": {
+ "end": lang.hitch(this, function(){
+ var barHeight = this.domNode.scrollHeight;
+ if(has("ff")){
+ barHeight -= 2;
+ }
+ return toShow ? (curHeight - barHeight) : (curHeight + barHeight);
+ })
+ }
+ }
+ };
+ array.forEach(g.views.views, function(view){
+ anims.push(baseFx.animateProperty(lang.mixin({
+ "node": view.domNode
+ }, prop, animArgs)), baseFx.animateProperty(lang.mixin({
+ "node": view.scrollboxNode
+ }, prop, animArgs)));
+ });
+ anims.push(baseFx.animateProperty(lang.mixin({
+ "node": g.viewsNode
+ }, prop, animArgs)));
+ fx.combine(anims).play();
+ }else{
+ html.style(this.domNode, "display", toShow ? "" : "none");
+ g.update();
+ }
+ },
+ toggleFilterBar: function(useAnim, animArgs){
+ this.showFilterBar(!this.isFilterBarShown(), useAnim, animArgs);
+ },
+ getColumnIdx: function(/* int */coordX){
+ var headers = query("[role='columnheader']", this.plugin.grid.viewsHeaderNode);
+ var idx = -1;
+ for(var i = headers.length - 1; i >= 0; --i){
+ var coord = html.position(headers[i]);
+ if(coordX >= coord.x && coordX < coord.x + coord.w){
+ idx = i;
+ break;
+ }
+ }
+ if(idx >= 0 && this.plugin.grid.layout.cells[idx].filterable !== false){
+ return idx; //Integer
+ }else{
+ return -1; //Integer
+ }
+ },
+ toggleClearFilterBtn: function(toHide){
+ html.style(this.clearFilterButton.domNode, "display", toHide ? "none" : "");
+ },
+ _closeFilterBar: function(e){
+ _stopEvent(e);
+ var rulesCnt = this.plugin.filterDefDialog.getCriteria();
+ if(rulesCnt){
+ var handle = connect.connect(this.plugin.filterDefDialog, "clearFilter", this, function(){
+ this.showFilterBar(false, true);
+ connect.disconnect(handle);
+ });
+ this._clearFilterDefDialog(e);
+ }else{
+ this.showFilterBar(false, true);
+ }
+ },
+
+ _showFilterDefDialog: function(e){
+ _stopEvent(e);
+ this.plugin.filterDefDialog.showDialog(this._curColIdx);
+ this.plugin.grid.focus.focusArea("filterbar");
+ },
+ _clearFilterDefDialog: function(e){
+ _stopEvent(e);
+ this.plugin.filterDefDialog.onClearFilter();
+ this.plugin.grid.focus.focusArea("filterbar");
+ },
+ _onEnterButton: function(e){
+ //If mouse is hovering the btn, which means the user is about to click,
+ //we should not show status tip on the btn!
+ this._onBlurFilterBar();
+ _stopEvent(e);
+ },
+ _onMoveButton: function(e){
+ this._onBlurFilterBar();
+ },
+ _onLeaveButton: function(e){
+ this._leavingBtn = true;
+ },
+ _onShowFilterDefDialog: function(/* Integer */colIdx){
+ if(typeof colIdx == "number"){
+ this._curColIdx = colIdx;
+ }
+ this._defPaneIsShown = true;
+ },
+ _onCloseFilterDefDialog: function(){
+ this._defPaneIsShown = false;
+ //Do not remember what column are we on, so clicking the btn will show 'any column'
+ this._curColIdx = -1;
+ dijitFocus.focus(this.defineFilterButton.domNode);
+ },
+ _onClickFilterBar: function(/* event */e){
+ _stopEvent(e);
+ this._clearStatusTipTimeout();
+ this.plugin.grid.focus.focusArea("filterbar");
+ this.plugin.filterDefDialog.showDialog(this.getColumnIdx(e.clientX));
+ },
+ _onMouseEnter: function(/* event */e){
+ this._onFocusFilterBar(true, null);
+ this._updateTipPosition(e);
+ this._setStatusTipTimeout();
+ },
+ _onMouseMove: function(/* event */e){
+ if(this._leavingBtn){
+ this._onFocusFilterBar(true, null);
+ this._leavingBtn = false;
+ }
+ if(this._isFocused){
+ this._setStatusTipTimeout();
+ this._highlightHeader(this.getColumnIdx(e.clientX));
+ if(this._handle_statusTooltip){
+ this._updateTipPosition(e);
+ }
+ }
+ },
+ _onMouseLeave: function(e){
+ this._onBlurFilterBar();
+ },
+ _updateTipPosition: function(evt){
+ this._tippos = {
+ x: evt.pageX,
+ y: evt.pageY
+ };
+ },
+ _onFocusFilterBar: function(highlightOnly, evt, step){
+ if(!this.isFilterBarShown()){
+ return false;
+ }
+ this._isFocused = true;
+ html.addClass(this.domNode,_focusClass);
+ if(!highlightOnly){
+ var hasFilter = html.style(this.clearFilterButton.domNode, "display") !== "none";
+ var hasCloseButton = html.style(this.closeFilterBarButton.domNode, "display") !== "none";
+ if(typeof this._focusPos == "undefined"){
+ if(step > 0){
+ this._focusPos = 0;
+ }else{
+ if(hasCloseButton){
+ this._focusPos = 1;
+ }else{
+ this._focusPos = 0;
+ }
+ if(hasFilter){
+ ++this._focusPos;
+ }
+ }
+ }
+ if(this._focusPos === 0){
+ dijitFocus.focus(this.defineFilterButton.focusNode);
+ }else if(this._focusPos === 1 && hasFilter){
+ dijitFocus.focus(this.clearFilterButton.focusNode);
+ }else{
+ dijitFocus.focus(this.closeFilterBarButton.focusNode);
+ }
+ }
+ _stopEvent(evt);
+ return true;
+ },
+ _onBlurFilterBar: function(evt, step){
+ if(this._isFocused){
+ this._isFocused = false;
+ html.removeClass(this.domNode,_focusClass);
+ this._clearStatusTipTimeout();
+ this._clearHeaderHighlight();
+ }
+ var toBlur = true;
+ if(step){
+ var buttonCount = 3;
+ if(html.style(this.closeFilterBarButton.domNode, "display") === "none"){
+ --buttonCount;
+ }
+ if(html.style(this.clearFilterButton.domNode, "display") === "none"){
+ --buttonCount;
+ }
+ if(buttonCount == 1){
+ delete this._focusPos;
+ }else{
+ var current = this._focusPos;
+ for(var next = current + step; next < 0; next += buttonCount){}
+ next %= buttonCount;
+ if((step > 0 && next < current) || (step < 0 && next > current)){
+ delete this._focusPos;
+ }else{
+ this._focusPos = next;
+ toBlur = false;
+ }
+ }
+ }
+ return toBlur;
+ },
+ _onFiltered: function(/* int */filteredSize,/* int */originSize){
+ var p = this.plugin,
+ itemsName = p.args.itemsName || p.nls["defaultItemsName"],
+ msg = "", g = p.grid,
+ filterLayer = g.layer("filter");
+ if(filterLayer.filterDef()){
+ msg = string.substitute(p.nls["filterBarMsgHasFilterTemplate"], [filteredSize, originSize, itemsName]);
+ html.addClass(this.domNode, _filteredClass);
+ }else{
+ msg = string.substitute(p.nls["filterBarMsgNoFilterTemplate"], [originSize, itemsName]);
+ html.removeClass(this.domNode, _filteredClass);
+ }
+ this.statusBarNode.innerHTML = msg;
+ this._focusPos = 0;
+ },
+ _initAriaInfo: function(){
+ this.defineFilterButton.domNode.setAttribute("aria-label", this.plugin.nls["waiFilterBarDefButton"]);
+ this.clearFilterButton.domNode.setAttribute("aria-label", this.plugin.nls["waiFilterBarClearButton"]);
+ },
+ _isInColumn: function(/* int */mousePos_x, /* domNode */headerNode, /* int */colIndex){
+ var coord = html.position(headerNode);
+ return mousePos_x >= coord.x && mousePos_x < coord.x + coord.w;
+ },
+ _setStatusTipTimeout: function(){
+ this._clearStatusTipTimeout();
+ if(!this._defPaneIsShown){
+ this._handle_statusTooltip = setTimeout(lang.hitch(this,this._showStatusTooltip),this._timeout_statusTooltip);
+ }
+ },
+ _clearStatusTipTimeout: function(){
+ clearTimeout(this._handle_statusTooltip);
+ this._handle_statusTooltip = null;
+ },
+ _showStatusTooltip: function(){
+ this._handle_statusTooltip = null;
+ this.plugin.filterStatusTip.showDialog(this._tippos.x, this._tippos.y, this.getColumnIdx(this._tippos.x));
+ },
+ _highlightHeader: function(/* int */colIdx){
+ if(colIdx != this._previousHeaderIdx){
+ var g = this.plugin.grid,
+ cell = g.getCell(this._previousHeaderIdx);
+ if(cell){
+ html.removeClass(cell.getHeaderNode(), "dojoxGridCellOver");
+ }
+ cell = g.getCell(colIdx);
+ if(cell){
+ html.addClass(cell.getHeaderNode(), "dojoxGridCellOver");
+ }
+ this._previousHeaderIdx = colIdx;
+ }
+ },
+ _clearHeaderHighlight: function(){
+ if(typeof this._previousHeaderIdx != "undefined"){
+ var g = this.plugin.grid,
+ cell = g.getCell(this._previousHeaderIdx);
+ if(cell){
+ g.onHeaderCellMouseOut({
+ cellNode: cell.getHeaderNode()
+ });
+ }
+ delete this._previousHeaderIdx;
+ }
+ }
+});
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/filter/FilterBuilder.js b/js/dojo/dojox/grid/enhanced/plugins/filter/FilterBuilder.js
new file mode 100644
index 0000000..63297c0
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/filter/FilterBuilder.js
@@ -0,0 +1,81 @@
+//>>built
+define("dojox/grid/enhanced/plugins/filter/FilterBuilder", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/lang",
+ "./_FilterExpr"
+], function(declare, array, lang, exprs){
+
+var bdr = function(opCls){
+ return lang.partial(function(cls,operands){
+ return new exprs[cls](operands);
+ },opCls);
+ },
+ bdr_not = function(opCls){
+ return lang.partial(function(cls,operands){
+ return new exprs.LogicNOT(new exprs[cls](operands));
+ },opCls);
+ };
+return declare("dojox.grid.enhanced.plugins.filter.FilterBuilder", null, {
+ // summary:
+ // Create filter expression from a JSON object.
+ buildExpression: function(def){
+ if("op" in def){
+ return this.supportedOps[def.op.toLowerCase()](array.map(def.data, this.buildExpression, this));
+ }else{
+ var args = lang.mixin(this.defaultArgs[def.datatype], def.args || {});
+ return new this.supportedTypes[def.datatype](def.data, def.isColumn, args);
+ }
+ },
+ supportedOps: {
+ // summary:
+ // The builders of all supported operations
+ "equalto": bdr("EqualTo"),
+ "lessthan": bdr("LessThan"),
+ "lessthanorequalto": bdr("LessThanOrEqualTo"),
+ "largerthan": bdr("LargerThan"),
+ "largerthanorequalto": bdr("LargerThanOrEqualTo"),
+ "contains": bdr("Contains"),
+ "startswith": bdr("StartsWith"),
+ "endswith": bdr("EndsWith"),
+ "notequalto": bdr_not("EqualTo"),
+ "notcontains": bdr_not("Contains"),
+ "notstartswith": bdr_not("StartsWith"),
+ "notendswith": bdr_not("EndsWith"),
+ "isempty": bdr("IsEmpty"),
+ "range": function(operands){
+ return new exprs.LogicALL(
+ new exprs.LargerThanOrEqualTo(operands.slice(0,2)),
+ new exprs.LessThanOrEqualTo(operands[0], operands[2])
+ );
+ },
+ "logicany": bdr("LogicANY"),
+ "logicall": bdr("LogicALL")
+ },
+ supportedTypes: {
+ "number": exprs.NumberExpr,
+ "string": exprs.StringExpr,
+ "boolean": exprs.BooleanExpr,
+ "date": exprs.DateExpr,
+ "time": exprs.TimeExpr
+ },
+ defaultArgs: {
+ "boolean": {
+ "falseValue": "false",
+ "convert": function(dataValue, args){
+ var falseValue = args.falseValue;
+ var trueValue = args.trueValue;
+ if(lang.isString(dataValue)){
+ if(trueValue && dataValue.toLowerCase() == trueValue){
+ return true;
+ }
+ if(falseValue && dataValue.toLowerCase() == falseValue){
+ return false;
+ }
+ }
+ return !!dataValue;
+ }
+ }
+ }
+});
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/filter/FilterDefDialog.js b/js/dojo/dojox/grid/enhanced/plugins/filter/FilterDefDialog.js
new file mode 100644
index 0000000..7e49153
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/filter/FilterDefDialog.js
@@ -0,0 +1,1252 @@
+//>>built
+define("dojox/grid/enhanced/plugins/filter/FilterDefDialog", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "dojo/_base/lang",
+ "dojo/_base/event",
+ "dojo/_base/html",
+ "dojo/_base/sniff",
+ "dojo/cache",
+ "dojo/keys",
+ "dojo/string",
+ "dojo/window",
+ "dojo/date/locale",
+ "./FilterBuilder",
+ "../Dialog",
+ "dijit/form/ComboBox",
+ "dijit/form/TextBox",
+ "dijit/form/NumberTextBox",
+ "dijit/form/DateTextBox",
+ "dijit/form/TimeTextBox",
+ "dijit/form/Button",
+ "dijit/layout/AccordionContainer",
+ "dijit/layout/ContentPane",
+ "dijit/_Widget",
+ "dijit/_TemplatedMixin",
+ "dijit/_WidgetsInTemplateMixin",
+ "dijit/focus",
+ "dojox/html/metrics",
+ "dijit/a11y",
+ "dijit/Tooltip",
+ "dijit/form/Select",
+ "dijit/form/RadioButton",
+ "dojox/html/ellipsis",
+ "../../../cells/dijit"
+], function(declare, array, connect, lang, event, html, has, cache, keys, string, win, dateLocale,
+ FilterBuilder, Dialog, ComboBox, TextBox, NumberTextBox, DateTextBox, TimeTextBox, Button,
+ AccordionContainer, ContentPane, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, dijitFocus, metrics, dijitA11y){
+
+var _tabIdxes = {
+ // summary:
+ // Define tabindexes for elements in the filter definition dialog
+ relSelect: 60,
+ accordionTitle: 70,
+ removeCBoxBtn: -1,
+ colSelect: 90,
+ condSelect: 95,
+ valueBox: 10,
+ addCBoxBtn: 20,
+ filterBtn: 30,
+ clearBtn: 40,
+ cancelBtn: 50
+ };
+var FilterAccordionContainer = declare("dojox.grid.enhanced.plugins.filter.AccordionContainer", AccordionContainer, {
+ nls: null,
+ addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
+ var pane = arguments[0] = child._pane = new ContentPane({
+ content: child
+ });
+ this.inherited(arguments);
+ this._modifyChild(pane);
+ },
+ removeChild: function(child){
+ var pane = child, isRemoveByUser = false;
+ if(child._pane){
+ isRemoveByUser = true;
+ pane = arguments[0] = child._pane;
+ }
+ this.inherited(arguments);
+ if(isRemoveByUser){
+ this._hackHeight(false, this._titleHeight);
+ var children = this.getChildren();
+ if(children.length === 1){
+ html.style(children[0]._removeCBoxBtn.domNode, "display", "none");
+ }
+ }
+ pane.destroyRecursive();
+ },
+ selectChild: function(child){
+ if(child._pane){
+ arguments[0] = child._pane;
+ }
+ this.inherited(arguments);
+ },
+ resize: function(){
+ this.inherited(arguments);
+ array.forEach(this.getChildren(), this._setupTitleDom);
+ },
+ startup: function(){
+ if(this._started){
+ return;
+ }
+ this.inherited(arguments);
+ if(parseInt(has("ie"), 10) == 7){
+ //IE7 will fire a lot of "onresize" event during initialization.
+ array.some(this._connects, function(cnnt){
+ if(cnnt[0][1] == "onresize"){
+ this.disconnect(cnnt);
+ return true;
+ }
+ }, this);
+ }
+ array.forEach(this.getChildren(), function(child){
+ this._modifyChild(child, true);
+ }, this);
+ },
+ _onKeyPress: function(/*Event*/ e, /*dijit._Widget*/ fromTitle){
+ // summary:
+ // Overrides base class method, make left/right button do other things.
+ if(this.disabled || e.altKey || !(fromTitle || e.ctrlKey)){
+ return;
+ }
+ var k = keys, c = e.charOrCode, ltr = html._isBodyLtr(), toNext = null;
+ if((fromTitle && c == k.UP_ARROW) || (e.ctrlKey && c == k.PAGE_UP)){
+ toNext = false;
+ }else if((fromTitle && c == k.DOWN_ARROW) || (e.ctrlKey && (c == k.PAGE_DOWN || c == k.TAB))){
+ toNext = true;
+ }else if(c == (ltr ? k.LEFT_ARROW : k.RIGHT_ARROW)){
+ toNext = this._focusOnRemoveBtn ? null : false;
+ this._focusOnRemoveBtn = !this._focusOnRemoveBtn;
+ }else if(c == (ltr ? k.RIGHT_ARROW : k.LEFT_ARROW)){
+ toNext = this._focusOnRemoveBtn ? true : null;
+ this._focusOnRemoveBtn = !this._focusOnRemoveBtn;
+ }else{
+ return;
+ }
+ if(toNext !== null){
+ this._adjacent(toNext)._buttonWidget._onTitleClick();
+ }
+ event.stop(e);
+ win.scrollIntoView(this.selectedChildWidget._buttonWidget.domNode.parentNode);
+ if(has("ie")){
+ //IE will not show focus indicator if tabIndex is -1
+ this.selectedChildWidget._removeCBoxBtn.focusNode.setAttribute("tabIndex", this._focusOnRemoveBtn ? _tabIdxes.accordionTitle : -1);
+ }
+ dijitFocus.focus(this.selectedChildWidget[this._focusOnRemoveBtn ? "_removeCBoxBtn" : "_buttonWidget"].focusNode);
+ },
+ _modifyChild: function(child, isFirst){
+ if(!child || !this._started){
+ return;
+ }
+ html.style(child.domNode, "overflow", "hidden");
+ child._buttonWidget.connect(child._buttonWidget, "_setSelectedAttr", function(){
+ this.focusNode.setAttribute("tabIndex", this.selected ? _tabIdxes.accordionTitle : "-1");
+ });
+ var _this = this;
+ child._buttonWidget.connect(child._buttonWidget.domNode, "onclick", function(){
+ _this._focusOnRemoveBtn = false;
+ });
+ (child._removeCBoxBtn = new Button({
+ label: this.nls.removeRuleButton,
+ showLabel: false,
+ iconClass: "dojoxGridFCBoxRemoveCBoxBtnIcon",
+ tabIndex: _tabIdxes.removeCBoxBtn,
+ onClick: lang.hitch(child.content, "onRemove"),
+ onKeyPress: function(e){
+ _this._onKeyPress(e, child._buttonWidget.contentWidget);
+ }
+ })).placeAt(child._buttonWidget.domNode);
+ var i, children = this.getChildren();
+ if(children.length === 1){
+ child._buttonWidget.set("selected", true);
+ html.style(child._removeCBoxBtn.domNode, "display", "none");
+ }else{
+ for(i = 0; i < children.length; ++i){
+ if(children[i]._removeCBoxBtn){
+ html.style(children[i]._removeCBoxBtn.domNode, "display", "");
+ }
+ }
+ }
+ this._setupTitleDom(child);
+ if(!this._titleHeight){
+ for(i = 0; i < children.length; ++i){
+ if(children[i] != this.selectedChildWidget){
+ this._titleHeight = html.marginBox(children[i]._buttonWidget.domNode.parentNode).h;
+ break;
+ }
+ }
+ }
+ if(!isFirst){
+ this._hackHeight(true, this._titleHeight);
+ }
+ },
+ _hackHeight: function(/* bool */toGrow,/* int */heightDif){
+ var children = this.getChildren(),
+ dn = this.domNode, h = html.style(dn, "height");
+ if(!toGrow){
+ dn.style.height = (h - heightDif) + 'px';
+ }else if(children.length > 1){
+ dn.style.height = (h + heightDif) + 'px';
+ }else{
+ //Only one rule, no need to do anything.
+ return;
+ }
+ this.resize();
+ },
+ _setupTitleDom: function(child){
+ var w = html.contentBox(child._buttonWidget.titleNode).w;
+ if(has("ie") < 8){ w -= 8; }
+ html.style(child._buttonWidget.titleTextNode, "width", w + "px");
+ }
+});
+var FilterDefPane = declare("dojox.grid.enhanced.plugins.filter.FilterDefPane",[_Widget, _TemplatedMixin, _WidgetsInTemplateMixin],{
+ templateString: cache("dojox.grid","enhanced/templates/FilterDefPane.html"),
+ widgetsInTemplate: true,
+ dlg: null,
+ postMixInProperties: function(){
+ this.plugin = this.dlg.plugin;
+ var nls = this.plugin.nls;
+ this._addRuleBtnLabel = nls.addRuleButton;
+ this._cancelBtnLabel = nls.cancelButton;
+ this._clearBtnLabel = nls.clearButton;
+ this._filterBtnLabel = nls.filterButton;
+ this._relAll = nls.relationAll;
+ this._relAny = nls.relationAny;
+ this._relMsgFront = nls.relationMsgFront;
+ this._relMsgTail = nls.relationMsgTail;
+ },
+ postCreate: function(){
+ this.inherited(arguments);
+ this.connect(this.domNode, "onkeypress", "_onKey");
+ (this.cboxContainer = new FilterAccordionContainer({
+ nls: this.plugin.nls
+ })).placeAt(this.criteriaPane);
+
+ this._relSelect.set("tabIndex", _tabIdxes.relSelect);
+ this._addCBoxBtn.set("tabIndex", _tabIdxes.addCBoxBtn);
+ this._cancelBtn.set("tabIndex", _tabIdxes.cancelBtn);
+ this._clearFilterBtn.set("tabIndex", _tabIdxes.clearBtn);
+ this._filterBtn.set("tabIndex", _tabIdxes.filterBtn);
+
+ var nls = this.plugin.nls;
+ this._relSelect.domNode.setAttribute("aria-label", nls.waiRelAll);
+ this._addCBoxBtn.domNode.setAttribute("aria-label", nls.waiAddRuleButton);
+ this._cancelBtn.domNode.setAttribute("aria-label", nls.waiCancelButton);
+ this._clearFilterBtn.domNode.setAttribute("aria-label", nls.waiClearButton);
+ this._filterBtn.domNode.setAttribute("aria-label", nls.waiFilterButton);
+
+ this._relSelect.set("value", this.dlg._relOpCls === "logicall" ? "0" : "1");
+ },
+ uninitialize: function(){
+ this.cboxContainer.destroyRecursive();
+ this.plugin = null;
+ this.dlg = null;
+ },
+ _onRelSelectChange: function(val){
+ this.dlg._relOpCls = val == "0" ? "logicall" : "logicany";
+ this._relSelect.domNode.setAttribute("aria-label", this.plugin.nls[val == "0" ? "waiRelAll" : "waiRelAny"]);
+ },
+ _onAddCBox: function(){
+ this.dlg.addCriteriaBoxes(1);
+ },
+ _onCancel: function(){
+ this.dlg.onCancel();
+ },
+ _onClearFilter: function(){
+ this.dlg.onClearFilter();
+ },
+ _onFilter: function(){
+ this.dlg.onFilter();
+ },
+ _onKey: function(e){
+ if(e.keyCode == keys.ENTER){
+ this.dlg.onFilter();
+ }
+ }
+});
+var CriteriaBox = declare("dojox.grid.enhanced.plugins.filter.CriteriaBox",[_Widget, _TemplatedMixin, _WidgetsInTemplateMixin],{
+ templateString: cache("dojox.grid","enhanced/templates/CriteriaBox.html"),
+ widgetsInTemplate: true,
+ dlg: null,
+ postMixInProperties: function(){
+ this.plugin = this.dlg.plugin;
+ this._curValueBox = null;
+
+ var nls = this.plugin.nls;
+ this._colSelectLabel = nls.columnSelectLabel;
+ this._condSelectLabel = nls.conditionSelectLabel;
+ this._valueBoxLabel = nls.valueBoxLabel;
+ this._anyColumnOption = nls.anyColumnOption;
+ },
+ postCreate: function(){
+ var dlg = this.dlg, g = this.plugin.grid;
+ //Select Column
+ this._colSelect.set("tabIndex", _tabIdxes.colSelect);
+ this._colOptions = this._getColumnOptions();
+ this._colSelect.addOption([
+ {label: this.plugin.nls.anyColumnOption, value: "anycolumn", selected: dlg.curColIdx < 0},
+ {value: ""}
+ ].concat(this._colOptions));
+ //Select Condition
+ this._condSelect.set("tabIndex", _tabIdxes.condSelect);
+ this._condSelect.addOption(this._getUsableConditions(dlg.getColumnType(dlg.curColIdx)));
+ this._showSelectOrLabel(this._condSelect, this._condSelectAlt);
+
+ this.connect(g.layout, "moveColumn", "onMoveColumn");
+ },
+ _getColumnOptions: function(){
+ var colIdx = this.dlg.curColIdx >= 0 ? String(this.dlg.curColIdx) : "anycolumn";
+ return array.map(array.filter(this.plugin.grid.layout.cells, function(cell){
+ return !(cell.filterable === false || cell.hidden);
+ }), function(cell){
+ return {
+ label: cell.name || cell.field,
+ value: String(cell.index),
+ selected: colIdx == String(cell.index)
+ };
+ });
+ },
+ onMoveColumn: function(){
+ var tmp = this._onChangeColumn;
+ this._onChangeColumn = function(){};
+ var option = this._colSelect.get("selectedOptions");
+ this._colSelect.removeOption(this._colOptions);
+ this._colOptions = this._getColumnOptions();
+ this._colSelect.addOption(this._colOptions);
+ var i = 0;
+ for(; i < this._colOptions.length; ++i){
+ if(this._colOptions[i].label == option.label){
+ break;
+ }
+ }
+ if(i < this._colOptions.length){
+ this._colSelect.set("value", this._colOptions[i].value);
+ }
+ var _this = this;
+ setTimeout(function(){
+ _this._onChangeColumn = tmp;
+ }, 0);
+ },
+ onRemove: function(){
+ this.dlg.removeCriteriaBoxes(this);
+ },
+ uninitialize: function(){
+ if(this._curValueBox){
+ this._curValueBox.destroyRecursive();
+ this._curValueBox = null;
+ }
+ this.plugin = null;
+ this.dlg = null;
+ },
+ _showSelectOrLabel: function(sel, alt){
+ var options = sel.getOptions();
+ if(options.length == 1){
+ alt.innerHTML = options[0].label;
+ html.style(sel.domNode, "display", "none");
+ html.style(alt, "display", "");
+ }else{
+ html.style(sel.domNode, "display", "");
+ html.style(alt, "display", "none");
+ }
+ },
+ _onChangeColumn: function(val){
+ this._checkValidCriteria();
+ var type = this.dlg.getColumnType(val);
+ this._setConditionsByType(type);
+ this._setValueBoxByType(type);
+ this._updateValueBox();
+ },
+ _onChangeCondition: function(val){
+ this._checkValidCriteria();
+ var f = (val == "range");
+ if(f ^ this._isRange){
+ this._isRange = f;
+ this._setValueBoxByType(this.dlg.getColumnType(this._colSelect.get("value")));
+ }
+ this._updateValueBox();
+ },
+ _updateValueBox: function(cond){
+ this._curValueBox.set("disabled", this._condSelect.get("value") == "isempty");
+ },
+ _checkValidCriteria: function(){
+ // summary:
+ // Check whether the given criteria box is completed. If it is, mark it.
+ setTimeout(lang.hitch(this, function(){
+ this.updateRuleTitle();
+ this.dlg._updatePane();
+ }),0);
+ },
+ _createValueBox: function(/* widget constructor */cls,/* object */arg){
+ // summary:
+ // Create a value input box with given class and arguments
+ var func = lang.hitch(arg.cbox, "_checkValidCriteria");
+ return new cls(lang.mixin(arg,{
+ tabIndex: _tabIdxes.valueBox,
+ onKeyPress: func,
+ onChange: func,
+ "class": "dojoxGridFCBoxValueBox"
+ }));
+ },
+ _createRangeBox: function(/* widget constructor */cls,/* object */arg){
+ // summary:
+ // Create a DIV containing 2 input widgets, which represents a range, with the given class and arguments
+ var func = lang.hitch(arg.cbox, "_checkValidCriteria");
+ lang.mixin(arg,{
+ tabIndex: _tabIdxes.valueBox,
+ onKeyPress: func,
+ onChange: func
+ });
+ var div = html.create("div", {"class": "dojoxGridFCBoxValueBox"}),
+ start = new cls(arg),
+ txt = html.create("span", {"class": "dojoxGridFCBoxRangeValueTxt", "innerHTML": this.plugin.nls.rangeTo}),
+ end = new cls(arg);
+ html.addClass(start.domNode, "dojoxGridFCBoxStartValue");
+ html.addClass(end.domNode, "dojoxGridFCBoxEndValue");
+ div.appendChild(start.domNode);
+ div.appendChild(txt);
+ div.appendChild(end.domNode);
+ div.domNode = div;
+ //Mock functions for set and get (in place of the old attr function)
+ div.set = function(dummy, args){
+ if(lang.isObject(args)){
+ start.set("value", args.start);
+ end.set("value", args.end);
+ }
+ };
+ div.get = function(){
+ var s = start.get("value"),
+ e = end.get("value");
+ return s && e ? {start: s, end: e} : "";
+ };
+ return div;
+ },
+ changeCurrentColumn: function(/* bool */selectCurCol){
+ var colIdx = this.dlg.curColIdx;
+ //Re-populate the columns in case some of them are set to hidden.
+ this._colSelect.removeOption(this._colOptions);
+ this._colOptions = this._getColumnOptions();
+ this._colSelect.addOption(this._colOptions);
+ this._colSelect.set('value', colIdx >= 0 ? String(colIdx) : "anycolumn");
+ this.updateRuleTitle(true);
+ },
+ curColumn: function(){
+ return this._colSelect.getOptions(this._colSelect.get("value")).label;
+ },
+ curCondition: function(){
+ return this._condSelect.getOptions(this._condSelect.get("value")).label;
+ },
+ curValue: function(){
+ var cond = this._condSelect.get("value");
+ if(cond == "isempty"){return "";}
+ return this._curValueBox ? this._curValueBox.get("value") : "";
+ },
+ save: function(){
+ if(this.isEmpty()){
+ return null;
+ }
+ var colIdx = this._colSelect.get("value"),
+ type = this.dlg.getColumnType(colIdx),
+ value = this.curValue(),
+ cond = this._condSelect.get("value");
+ return {
+ "column": colIdx,
+ "condition": cond,
+ "value": value,
+ "formattedVal": this.formatValue(type, cond, value),
+ "type": type,
+ "colTxt": this.curColumn(),
+ "condTxt": this.curCondition()
+ };
+ },
+ load: function(obj){
+ var tmp = [
+ this._onChangeColumn,
+ this._onChangeCondition
+ ];
+ this._onChangeColumn = this._onChangeCondition = function(){};
+ if(obj.column){
+ this._colSelect.set("value", obj.column);
+ }
+ if(obj.condition){
+ this._condSelect.set("value", obj.condition);
+ }
+ if(obj.type){
+ this._setValueBoxByType(obj.type);
+ }else{
+ obj.type = this.dlg.getColumnType(this._colSelect.get("value"));
+ }
+ var value = obj.value || "";
+ if(value || (obj.type != "date" && obj.type != "time")){
+ this._curValueBox.set("value", value);
+ }
+ this._updateValueBox();
+ setTimeout(lang.hitch(this, function(){
+ this._onChangeColumn = tmp[0];
+ this._onChangeCondition = tmp[1];
+ }), 0);
+ },
+ getExpr: function(){
+ if(this.isEmpty()){
+ return null;
+ }
+ var colval = this._colSelect.get("value");
+ return this.dlg.getExprForCriteria({
+ "type": this.dlg.getColumnType(colval),
+ "column": colval,
+ "condition": this._condSelect.get("value"),
+ "value": this.curValue()
+ });
+ },
+ isEmpty: function(){
+ var cond = this._condSelect.get("value");
+ if(cond == "isempty"){return false;}
+ var v = this.curValue();
+ return v === "" || v === null || typeof v == "undefined" || (typeof v == "number" && isNaN(v));
+ },
+ updateRuleTitle: function(isEmpty){
+ var node = this._pane._buttonWidget.titleTextNode;
+ var title = [
+ "<div class='dojoxEllipsis'>"
+ ];
+ if(isEmpty || this.isEmpty()){
+ node.title = string.substitute(this.plugin.nls.ruleTitleTemplate, [this._ruleIndex || 1]);
+ title.push(node.title);
+ }else{
+ var type = this.dlg.getColumnType(this._colSelect.get("value"));
+ var column = this.curColumn();
+ var condition = this.curCondition();
+ var value = this.formatValue(type, this._condSelect.get("value"), this.curValue());
+ title.push(
+ column,
+ "&nbsp;<span class='dojoxGridRuleTitleCondition'>",
+ condition,
+ "</span>&nbsp;",
+ value
+ );
+ node.title = [column, " ", condition, " ", value].join('');
+ }
+ node.innerHTML = title.join('');
+ if(has("mozilla")){
+ var tt = html.create("div", {
+ "style": "width: 100%; height: 100%; position: absolute; top: 0; left: 0; z-index: 9999;"
+ }, node);
+ tt.title = node.title;
+ }
+ },
+ updateRuleIndex: function(index){
+ if(this._ruleIndex != index){
+ this._ruleIndex = index;
+ if(this.isEmpty()){
+ this.updateRuleTitle();
+ }
+ }
+ },
+ setAriaInfo: function(idx){
+ var dss = string.substitute, nls = this.plugin.nls;
+ this._colSelect.domNode.setAttribute("aria-label", dss(nls.waiColumnSelectTemplate, [idx]));
+ this._condSelect.domNode.setAttribute("aria-label", dss(nls.waiConditionSelectTemplate, [idx]));
+ this._pane._removeCBoxBtn.domNode.setAttribute("aria-label", dss(nls.waiRemoveRuleButtonTemplate, [idx]));
+ this._index = idx;
+ },
+ _getUsableConditions: function(type){
+ var conditions = lang.clone(this.dlg._dataTypeMap[type].conditions);
+ var typeDisabledConds = (this.plugin.args.disabledConditions || {})[type];
+ var colIdx = parseInt(this._colSelect.get("value"), 10);
+ var colDisabledConds = isNaN(colIdx) ?
+ (this.plugin.args.disabledConditions || {})["anycolumn"] :
+ this.plugin.grid.layout.cells[colIdx].disabledConditions;
+ if(!lang.isArray(typeDisabledConds)){
+ typeDisabledConds = [];
+ }
+ if(!lang.isArray(colDisabledConds)){
+ colDisabledConds = [];
+ }
+ var arr = typeDisabledConds.concat(colDisabledConds);
+ if(arr.length){
+ var disabledConds = {};
+ array.forEach(arr, function(c){
+ if(lang.isString(c)){
+ disabledConds[c.toLowerCase()] = true;
+ }
+ });
+ return array.filter(conditions, function(condOption){
+ return !(condOption.value in disabledConds);
+ });
+ }
+ return conditions;
+ },
+ _setConditionsByType: function(/* string */type){
+ var condSelect = this._condSelect;
+ condSelect.removeOption(condSelect.options);
+ condSelect.addOption(this._getUsableConditions(type));
+ this._showSelectOrLabel(this._condSelect, this._condSelectAlt);
+ },
+ _setValueBoxByType: function(/* string */type){
+ if(this._curValueBox){
+ this.valueNode.removeChild(this._curValueBox.domNode);
+ try{
+ this._curValueBox.destroyRecursive();
+ }catch(e){}
+ delete this._curValueBox;
+ }
+ //value box class
+ var vbcls = this.dlg._dataTypeMap[type].valueBoxCls[this._getValueBoxClsInfo(this._colSelect.get("value"), type)],
+ vboxArg = this._getValueBoxArgByType(type);
+ this._curValueBox = this[this._isRange ? "_createRangeBox" : "_createValueBox"](vbcls, vboxArg);
+ this.valueNode.appendChild(this._curValueBox.domNode);
+
+ //Can not move to setAriaInfo, 'cause the value box is created after the defpane is loaded.
+ this._curValueBox.domNode.setAttribute("aria-label", string.substitute(this.plugin.nls.waiValueBoxTemplate,[this._index]));
+ //Now our cbox is completely ready
+ this.dlg.onRendered(this);
+ },
+ //--------------------------UI Configuration--------------------------------------
+ _getValueBoxArgByType: function(/* string */type){
+ // summary:
+ // Get the arguments for the value box construction.
+ var g = this.plugin.grid,
+ cell = g.layout.cells[parseInt(this._colSelect.get("value"), 10)],
+ res = {
+ cbox: this
+ };
+ if(type == "string"){
+ if(cell && (cell.suggestion || cell.autoComplete)){
+ html.mixin(res, {
+ store: g.store,
+ searchAttr: cell.field || cell.name,
+ fetchProperties: {
+ sort: [{"attribute": cell.field || cell.name}],
+ query: g.query,
+ queryOptions: g.queryOptions
+ }
+ });
+ }
+ }else if(type == "boolean"){
+ html.mixin(res, this.dlg.builder.defaultArgs["boolean"]);
+ }
+ if(cell && cell.dataTypeArgs){
+ html.mixin(res, cell.dataTypeArgs);
+ }
+ return res;
+ },
+ formatValue: function(type, cond, v){
+ // summary:
+ // Format the value to be shown in tooltip.
+ if(cond == "isempty"){return "";}
+ if(type == "date" || type == "time"){
+ var opt = {selector: type},
+ fmt = dateLocale.format;
+ if(cond == "range"){
+ return string.substitute(this.plugin.nls.rangeTemplate, [fmt(v.start, opt), fmt(v.end, opt)]);
+ }
+ return fmt(v, opt);
+ }else if(type == "boolean"){
+ return v ? this._curValueBox._lblTrue : this._curValueBox._lblFalse;
+ }
+ return v;
+ },
+ _getValueBoxClsInfo: function(/* int|string */colIndex, /* string */type){
+ // summary:
+ // Decide which value box to use given data type and column index.
+ var cell = this.plugin.grid.layout.cells[parseInt(colIndex, 10)];
+ //Now we only need to handle string. But maybe we need to handle more types here in the future.
+ if(type == "string"){
+ return (cell && (cell.suggestion || cell.autoComplete)) ? "ac" : "dft";
+ }
+ return "dft";
+ }
+});
+
+
+var UniqueComboBox = declare("dojox.grid.enhanced.plugins.filter.UniqueComboBox", ComboBox, {
+ _openResultList: function(results){
+ var cache = {}, s = this.store, colName = this.searchAttr;
+ arguments[0] = array.filter(results, function(item){
+ var key = s.getValue(item, colName), existed = cache[key];
+ cache[key] = true;
+ return !existed;
+ });
+ this.inherited(arguments);
+ },
+ _onKey: function(evt){
+ if(evt.charOrCode === keys.ENTER && this._opened){
+ event.stop(evt);
+ }
+ this.inherited(arguments);
+ }
+});
+var BooleanValueBox = declare("dojox.grid.enhanced.plugins.filter.BooleanValueBox", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin], {
+ templateString: cache("dojox.grid","enhanced/templates/FilterBoolValueBox.html"),
+ widgetsInTemplate: true,
+ constructor: function(args){
+ var nls = args.cbox.plugin.nls;
+ this._baseId = args.cbox.id;
+ this._lblTrue = args.trueLabel || nls.trueLabel || "true";
+ this._lblFalse = args.falseLabel || nls.falseLabel || "false";
+ this.args = args;
+ },
+ postCreate: function(){
+ this.onChange();
+ },
+ onChange: function(){},
+
+ get: function(prop){
+ return this.rbTrue.get("checked");
+ },
+ set: function(prop, v){
+ this.inherited(arguments);
+ if(prop == "value"){
+ this.rbTrue.set("checked", !!v);
+ this.rbFalse.set("checked", !v);
+ }
+ }
+});
+var FilterDefDialog = declare("dojox.grid.enhanced.plugins.filter.FilterDefDialog", null, {
+ // summary:
+ // Create the filter definition UI.
+ curColIdx: -1,
+ _relOpCls: "logicall",
+ _savedCriterias: null,
+ plugin: null,
+ constructor: function(args){
+ var plugin = this.plugin = args.plugin;
+ this.builder = new FilterBuilder();
+ this._setupData();
+ this._cboxes = [];
+ this.defaultType = plugin.args.defaultType || "string";
+
+ (this.filterDefPane = new FilterDefPane({
+ "dlg": this
+ })).startup();
+ (this._defPane = new Dialog({
+ "refNode": this.plugin.grid.domNode,
+ "title": plugin.nls.filterDefDialogTitle,
+ "class": "dojoxGridFDTitlePane",
+ "iconClass": "dojoxGridFDPaneIcon",
+ "content": this.filterDefPane
+ })).startup();
+
+ this._defPane.connect(plugin.grid.layer('filter'), "filterDef", lang.hitch(this, "_onSetFilter"));
+ plugin.grid.setFilter = lang.hitch(this, "setFilter");
+ plugin.grid.getFilter = lang.hitch(this, "getFilter");
+ plugin.grid.getFilterRelation = lang.hitch(this, function(){
+ return this._relOpCls;
+ });
+
+ plugin.connect(plugin.grid.layout, "moveColumn", lang.hitch(this, "onMoveColumn"));
+ },
+ onMoveColumn: function(sourceViewIndex, destViewIndex, cellIndex, targetIndex, before){
+ if(this._savedCriterias && cellIndex != targetIndex){
+ if(before){ --targetIndex; }
+ var min = cellIndex < targetIndex ? cellIndex : targetIndex;
+ var max = cellIndex < targetIndex ? targetIndex : cellIndex;
+ var dir = targetIndex > min ? 1 : -1;
+ array.forEach(this._savedCriterias, function(sc){
+ var idx = parseInt(sc.column, 10);
+ if(!isNaN(idx) && idx >= min && idx <= max){
+ sc.column = String(idx == cellIndex ? idx + (max - min) * dir : idx - dir);
+ }
+ });
+ }
+ },
+ destroy: function(){
+ this._defPane.destroyRecursive();
+ this._defPane = null;
+ this.filterDefPane = null;
+ this.builder = null;
+ this._dataTypeMap = null;
+ this._cboxes = null;
+ var g = this.plugin.grid;
+ g.setFilter = null;
+ g.getFilter = null;
+ g.getFilterRelation = null;
+ this.plugin = null;
+ },
+ _setupData: function(){
+ var nls = this.plugin.nls;
+ this._dataTypeMap = {
+ // summary:
+ // All supported data types
+ "number":{
+ valueBoxCls: {
+ dft: NumberTextBox
+ },
+ conditions:[
+ {label: nls.conditionEqual, value: "equalto", selected: true},
+ {label: nls.conditionNotEqual, value: "notequalto"},
+ {label: nls.conditionLess, value: "lessthan"},
+ {label: nls.conditionLessEqual, value: "lessthanorequalto"},
+ {label: nls.conditionLarger, value: "largerthan"},
+ {label: nls.conditionLargerEqual, value: "largerthanorequalto"},
+ {label: nls.conditionIsEmpty, value: "isempty"}
+ ]
+ },
+ "string":{
+ valueBoxCls: {
+ dft: TextBox,
+ ac: UniqueComboBox //For autoComplete
+ },
+ conditions:[
+ {label: nls.conditionContains, value: "contains", selected: true},
+ {label: nls.conditionIs, value: "equalto"},
+ {label: nls.conditionStartsWith, value: "startswith"},
+ {label: nls.conditionEndWith, value: "endswith"},
+ {label: nls.conditionNotContain, value: "notcontains"},
+ {label: nls.conditionIsNot, value: "notequalto"},
+ {label: nls.conditionNotStartWith, value: "notstartswith"},
+ {label: nls.conditionNotEndWith, value: "notendswith"},
+ {label: nls.conditionIsEmpty, value: "isempty"}
+ ]
+ },
+ "date":{
+ valueBoxCls: {
+ dft: DateTextBox
+ },
+ conditions:[
+ {label: nls.conditionIs, value: "equalto", selected: true},
+ {label: nls.conditionBefore, value: "lessthan"},
+ {label: nls.conditionAfter, value: "largerthan"},
+ {label: nls.conditionRange, value: "range"},
+ {label: nls.conditionIsEmpty, value: "isempty"}
+ ]
+ },
+ "time":{
+ valueBoxCls: {
+ dft: TimeTextBox
+ },
+ conditions:[
+ {label: nls.conditionIs, value: "equalto", selected: true},
+ {label: nls.conditionBefore, value: "lessthan"},
+ {label: nls.conditionAfter, value: "largerthan"},
+ {label: nls.conditionRange, value: "range"},
+ {label: nls.conditionIsEmpty, value: "isempty"}
+ ]
+ },
+ "boolean": {
+ valueBoxCls: {
+ dft: BooleanValueBox
+ },
+ conditions: [
+ {label: nls.conditionIs, value: "equalto", selected: true},
+ {label: nls.conditionIsEmpty, value: "isempty"}
+ ]
+ }
+ };
+ },
+ setFilter: function(rules, ruleRelation){
+ rules = rules || [];
+ if(!lang.isArray(rules)){
+ rules = [rules];
+ }
+ var func = function(){
+ if(rules.length){
+ this._savedCriterias = array.map(rules, function(rule){
+ var type = rule.type || this.defaultType;
+ return {
+ "type": type,
+ "column": String(rule.column),
+ "condition": rule.condition,
+ "value": rule.value,
+ "colTxt": this.getColumnLabelByValue(String(rule.column)),
+ "condTxt": this.getConditionLabelByValue(type, rule.condition),
+ "formattedVal": rule.formattedVal || rule.value
+ };
+ }, this);
+ this._criteriasChanged = true;
+ if(ruleRelation === "logicall" || ruleRelation === "logicany"){
+ this._relOpCls = ruleRelation;
+ }
+ var exprs = array.map(rules, this.getExprForCriteria, this);
+ exprs = this.builder.buildExpression(exprs.length == 1 ? exprs[0] : {
+ "op": this._relOpCls,
+ "data": exprs
+ });
+ this.plugin.grid.layer("filter").filterDef(exprs);
+ this.plugin.filterBar.toggleClearFilterBtn(false);
+ }
+ this._closeDlgAndUpdateGrid();
+ };
+ if(this._savedCriterias){
+ this._clearWithoutRefresh = true;
+ var handle = connect.connect(this, "clearFilter", this, function(){
+ connect.disconnect(handle);
+ this._clearWithoutRefresh = false;
+ func.apply(this);
+ });
+ this.onClearFilter();
+ }else{
+ func.apply(this);
+ }
+ },
+ getFilter: function(){
+ return lang.clone(this._savedCriterias) || [];
+ },
+ getColumnLabelByValue: function(v){
+ var nls = this.plugin.nls;
+ if(v.toLowerCase() == "anycolumn"){
+ return nls["anyColumnOption"];
+ }else{
+ var cell = this.plugin.grid.layout.cells[parseInt(v, 10)];
+ return cell ? (cell.name || cell.field) : "";
+ }
+ },
+ getConditionLabelByValue: function(type, c){
+ var conditions = this._dataTypeMap[type].conditions;
+ for(var i = conditions.length - 1; i >= 0; --i){
+ var cond = conditions[i];
+ if(cond.value == c.toLowerCase()){
+ return cond.label;
+ }
+ }
+ return "";
+ },
+ addCriteriaBoxes: function(/* int */cnt){
+ // summary:
+ // Add *cnt* criteria boxes to the filter definition pane.
+ // Check overflow if necessary.
+ if(typeof cnt != "number" || cnt <= 0){
+ return;
+ }
+ var cbs = this._cboxes,
+ cc = this.filterDefPane.cboxContainer,
+ total = this.plugin.args.ruleCount,
+ len = cbs.length, cbox;
+ //If overflow, add to max rule count.
+ if(total > 0 && len + cnt > total){
+ cnt = total - len;
+ }
+ for(; cnt > 0; --cnt){
+ cbox = new CriteriaBox({
+ dlg: this
+ });
+ cbs.push(cbox);
+ cc.addChild(cbox);
+ }
+ //If there's no content box in it , AccordionContainer can not startup
+ cc.startup();
+ this._updatePane();
+ this._updateCBoxTitles();
+ cc.selectChild(cbs[cbs.length-1]);
+ //Asign an impossibly large scrollTop to scroll the criteria pane to the bottom.
+ this.filterDefPane.criteriaPane.scrollTop = 1000000;
+ if(cbs.length === 4){
+ if(has("ie") <= 6 && !this.__alreadyResizedForIE6){
+ var size = html.position(cc.domNode);
+ size.w -= metrics.getScrollbar().w;
+ cc.resize(size);
+ this.__alreadyResizedForIE6 = true;
+ }else{
+ cc.resize();
+ }
+ }
+ },
+ removeCriteriaBoxes: function(/* int|CriteriaBox|int[] */cnt,/* bool? */isIdx){
+ // summary:
+ // Remove criteria boxes from the filter definition pane.
+ var cbs = this._cboxes, cc = this.filterDefPane.cboxContainer,
+ len = cbs.length, start = len - cnt,
+ end = len - 1, cbox,
+ curIdx = array.indexOf(cbs, cc.selectedChildWidget.content);
+ if(lang.isArray(cnt)){
+ var i, idxes = cnt;
+ idxes.sort();
+ cnt = idxes.length;
+ //find a rule that's not deleted.
+ //must find and focus the last one, or the hack will not work.
+ for(i = len - 1; i >= 0 && array.indexOf(idxes, i) >= 0; --i){}
+ if(i >= 0){
+ //must select before remove
+ if(i != curIdx){
+ cc.selectChild(cbs[i]);
+ }
+ //idxes is sorted from small to large,
+ //so travel reversely won't need change index after delete from array.
+ for(i = cnt-1; i >= 0; --i){
+ if(idxes[i] >= 0 && idxes[i] < len){
+ cc.removeChild(cbs[idxes[i]]);
+ cbs.splice(idxes[i],1);
+ }
+ }
+ }
+ start = cbs.length;
+ }else{
+ if(isIdx === true){
+ if(cnt >= 0 && cnt < len){
+ start = end = cnt;
+ cnt = 1;
+ }else{
+ return;
+ }
+ }else{
+ if(cnt instanceof CriteriaBox){
+ cbox = cnt;
+ cnt = 1;
+ start = end = array.indexOf(cbs, cbox);
+ }else if(typeof cnt != "number" || cnt <= 0){
+ return;
+ }else if(cnt >= len){
+ cnt = end;
+ start = 1;
+ }
+ }
+ if(end < start){
+ return;
+ }
+ //must select before remove
+ if(curIdx >= start && curIdx <= end){
+ cc.selectChild(cbs[start ? start-1 : end+1]);
+ }
+ for(; end >= start; --end){
+ cc.removeChild(cbs[end]);
+ }
+ cbs.splice(start, cnt);
+ }
+ this._updatePane();
+ this._updateCBoxTitles();
+ if(cbs.length === 3){
+ //In ie6, resize back to the normal width will cause the title button look strange.
+ cc.resize();
+ }
+ },
+ getCriteria: function(/* int */idx){
+ // summary:
+ // Get the *idx*-th criteria.
+ if(typeof idx != "number"){
+ return this._savedCriterias ? this._savedCriterias.length : 0;
+ }
+ if(this._savedCriterias && this._savedCriterias[idx]){
+ return lang.mixin({
+ relation: this._relOpCls == "logicall" ? this.plugin.nls.and : this.plugin.nls.or
+ },this._savedCriterias[idx]);
+ }
+ return null;
+ },
+ getExprForCriteria: function(rule){
+ if(rule.column == "anycolumn"){
+ var cells = array.filter(this.plugin.grid.layout.cells, function(cell){
+ return !(cell.filterable === false || cell.hidden);
+ });
+ return {
+ "op": "logicany",
+ "data": array.map(cells, function(cell){
+ return this.getExprForColumn(rule.value, cell.index, rule.type, rule.condition);
+ }, this)
+ };
+ }else{
+ return this.getExprForColumn(rule.value, rule.column, rule.type, rule.condition);
+ }
+ },
+ getExprForColumn: function(value, colIdx, type, condition){
+ colIdx = parseInt(colIdx, 10);
+ var cell = this.plugin.grid.layout.cells[colIdx],
+ colName = cell.field || cell.name,
+ obj = {
+ "datatype": type || this.getColumnType(colIdx),
+ "args": cell.dataTypeArgs,
+ "isColumn": true
+ },
+ operands = [lang.mixin({"data": this.plugin.args.isServerSide ? colName : cell}, obj)];
+ obj.isColumn = false;
+ if(condition == "range"){
+ operands.push(lang.mixin({"data": value.start}, obj),
+ lang.mixin({"data": value.end}, obj));
+ }else if(condition != "isempty"){
+ operands.push(lang.mixin({"data": value}, obj));
+ }
+ return {
+ "op": condition,
+ "data": operands
+ };
+ },
+ getColumnType: function(/* int */colIndex){
+ var cell = this.plugin.grid.layout.cells[parseInt(colIndex, 10)];
+ if(!cell || !cell.datatype){
+ return this.defaultType;
+ }
+ var type = String(cell.datatype).toLowerCase();
+ return this._dataTypeMap[type] ? type : this.defaultType;
+ },
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////
+ clearFilter: function(noRefresh){
+ // summary:
+ // Clear filter definition.
+ if(!this._savedCriterias){
+ return;
+ }
+ this._savedCriterias = null;
+ this.plugin.grid.layer("filter").filterDef(null);
+ try{
+ this.plugin.filterBar.toggleClearFilterBtn(true);
+ this.filterDefPane._clearFilterBtn.set("disabled", true);
+ this.removeCriteriaBoxes(this._cboxes.length-1);
+ this._cboxes[0].load({});
+ }catch(e){
+ //Any error means the filter is defined outside this plugin.
+ }
+ if(noRefresh){
+ this.closeDialog();
+ }else{
+ this._closeDlgAndUpdateGrid();
+ }
+ },
+ showDialog: function(/* int */colIndex){
+ // summary:
+ // Show the filter defintion dialog.
+ this._defPane.show();
+ this.plugin.filterStatusTip.closeDialog();
+ this._prepareDialog(colIndex);
+ },
+ closeDialog: function(){
+ // summary:
+ // Close the filter definition dialog.
+ if(this._defPane.open){
+ this._defPane.hide();
+ }
+ },
+ onFilter: function(e){
+ // summary:
+ // Triggered when the "Filter" button is clicked.
+ if(this.canFilter()){
+ this._defineFilter();
+ this._closeDlgAndUpdateGrid();
+ this.plugin.filterBar.toggleClearFilterBtn(false);
+ }
+ },
+ onClearFilter: function(e){
+ // summary:
+ // Triggered when the "Clear" button is clicked.
+ if(this._savedCriterias){
+ if(this._savedCriterias.length >= this.plugin.ruleCountToConfirmClearFilter){
+ this.plugin.clearFilterDialog.show();
+ }else{
+ this.clearFilter(this._clearWithoutRefresh);
+ }
+ }
+ },
+ onCancel: function(e){
+ // summary:
+ // Triggered when the "Cancel" buttton is clicked.
+ var sc = this._savedCriterias;
+ var cbs = this._cboxes;
+ if(sc){
+ this.addCriteriaBoxes(sc.length - cbs.length);
+ this.removeCriteriaBoxes(cbs.length - sc.length);
+ array.forEach(sc, function(c, i){
+ cbs[i].load(c);
+ });
+ }else{
+ this.removeCriteriaBoxes(cbs.length - 1);
+ cbs[0].load({});
+ }
+ this.closeDialog();
+ },
+ onRendered: function(cbox){
+ // summary:
+ // Triggered when the rendering of the filter definition dialog is completely finished.
+ // cbox:
+ // Current visible criteria box
+ if(!has("ff")){
+ var elems = dijitA11y._getTabNavigable(html.byId(cbox.domNode));
+ dijitFocus.focus(elems.lowest || elems.first);
+ }else{
+ var dp = this._defPane;
+ dp._getFocusItems(dp.domNode);
+ dijitFocus.focus(dp._firstFocusItem);
+ }
+ },
+ _onSetFilter: function(filterDef){
+ // summary:
+ // If someone clear the filter def in the store directly, we must clear it in the UI.
+ // If someone defines a filter, don't know how to handle it!
+ if(filterDef === null && this._savedCriterias){
+ this.clearFilter();
+ }
+ },
+ _prepareDialog: function(/* int */colIndex){
+ var sc = this._savedCriterias,
+ cbs = this._cboxes, i, cbox;
+ this.curColIdx = colIndex;
+ if(!sc){
+ if(cbs.length === 0){
+ this.addCriteriaBoxes(1);
+ }else{
+ //Re-populate columns anyway, because we don't know when the column is set to hidden.
+ for(i = 0; (cbox = cbs[i]); ++i){
+ cbox.changeCurrentColumn();
+ }
+ }
+ }else if(this._criteriasChanged){
+ this.filterDefPane._relSelect.set("value", this._relOpCls === "logicall" ? "0" : "1");
+ this._criteriasChanged = false;
+ var needNewCBox = sc.length > cbs.length ? sc.length - cbs.length : 0;
+ this.addCriteriaBoxes(needNewCBox);
+ this.removeCriteriaBoxes(cbs.length - sc.length);
+ this.filterDefPane._clearFilterBtn.set("disabled", false);
+ for(i = 0; i < cbs.length - needNewCBox; ++i){
+ cbs[i].load(sc[i]);
+ }
+ if(needNewCBox > 0){
+ var handled = [], handle = connect.connect(this, "onRendered", function(cbox){
+ var i = array.indexOf(cbs, cbox);
+ if(!handled[i]){
+ handled[i] = true;
+ if(--needNewCBox === 0){
+ connect.disconnect(handle);
+ }
+ cbox.load(sc[i]);
+ }
+ });
+ }
+ }
+ //Since we're allowed to remove cboxes when the definition pane is not shown,
+ //we have to resize the container to have a correct _verticalSpace.
+ this.filterDefPane.cboxContainer.resize();
+ },
+ _defineFilter: function(){
+ var cbs = this._cboxes,
+ filterCboxes = function(method){
+ return array.filter(array.map(cbs, function(cbox){
+ return cbox[method]();
+ }), function(result){
+ return !!result;
+ });
+ },
+ exprs = filterCboxes("getExpr");
+ this._savedCriterias = filterCboxes("save");
+ exprs = exprs.length == 1 ? exprs[0] : {
+ "op": this._relOpCls,
+ "data": exprs
+ };
+ exprs = this.builder.buildExpression(exprs);
+
+ this.plugin.grid.layer("filter").filterDef(exprs);
+ this.filterDefPane._clearFilterBtn.set("disabled", false);
+ },
+ _updateCBoxTitles: function(){
+ for(var cbs = this._cboxes, i = cbs.length; i > 0; --i){
+ cbs[i - 1].updateRuleIndex(i);
+ cbs[i - 1].setAriaInfo(i);
+ }
+ },
+ _updatePane: function(){
+ var cbs = this._cboxes,
+ defPane = this.filterDefPane;
+ defPane._addCBoxBtn.set("disabled", cbs.length == this.plugin.args.ruleCount);
+ defPane._filterBtn.set("disabled", !this.canFilter());
+ },
+ canFilter: function(){
+ return array.filter(this._cboxes, function(cbox){
+ return !cbox.isEmpty();
+ }).length > 0;
+ },
+ _closeDlgAndUpdateGrid: function(){
+ this.closeDialog();
+ var g = this.plugin.grid;
+ g.showMessage(g.loadingMessage);
+ setTimeout(lang.hitch(g, g._refresh), this._defPane.duration + 10);
+ }
+});
+
+return FilterDefDialog;
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/filter/FilterLayer.js b/js/dojo/dojox/grid/enhanced/plugins/filter/FilterLayer.js
new file mode 100644
index 0000000..e8f7ac4
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/filter/FilterLayer.js
@@ -0,0 +1,411 @@
+//>>built
+define("dojox/grid/enhanced/plugins/filter/FilterLayer", [
+ "dojo/_base/declare",
+ "dojo/_base/lang",
+ "dojo/_base/window",
+ "dojo/_base/json",
+ "../_StoreLayer"
+], function(declare, lang, win, json, layers){
+
+ var cmdSetFilter = "filter",
+ cmdClearFilter = "clear",
+ hitchIfCan = function(scope, func){
+ return func ? lang.hitch(scope || win.global, func) : function(){};
+ },
+ shallowClone = function(obj){
+ var res = {};
+ if(obj && lang.isObject(obj)){
+ for(var name in obj){
+ res[name] = obj[name];
+ }
+ }
+ return res;
+ };
+ var _FilterLayerMixin = declare("dojox.grid.enhanced.plugins.filter._FilterLayerMixin", null, {
+/*=====
+ // _filter: _ConditionExpr
+ // The filter definition
+ _filter: null,
+
+ filterDef: function(filter){
+ // summary:
+ // Get/set/clear the filter definition
+ // tags:
+ // public
+ // filter: (_ConditionExpr|null)?
+ // null: clear filter definition
+ // undefined: it's getter
+ // returns:
+ // A filter definition if it's getter.
+ },
+=====*/
+ tags: ["sizeChange"],
+ name: function(){
+ // summary:
+ // override from _StoreLayer.name
+ return "filter"; //string
+ },
+ onFilterDefined: function(filter){},
+
+ onFiltered: function(filteredSize, totalSize){
+ // summary:
+ // Called when store data is filtered. This event is before *onComplete*, after *onBegin*.
+ // tags:
+ // callback extension
+ // filteredSize: Integer
+ // The number of remaining fetched items after filtering.
+ // totalSize: Integer
+ // The number of original fetched items.
+ }
+ });
+ var ServerSideFilterLayer = declare("dojox.grid.enhanced.plugins.filter.ServerSideFilterLayer", [layers._ServerSideLayer, _FilterLayerMixin], {
+ constructor: function(args){
+ this._onUserCommandLoad = args.setupFilterQuery || this._onUserCommandLoad;
+ this.filterDef(null);
+ },
+ filterDef: function(/* (_ConditionExpr|null)? */filter){
+ // summary:
+ // See _FilterLayerMixin.filterDef
+ if(filter){
+ this._filter = filter;
+ var obj = filter.toObject();
+ //Stateless implementation will need to parse the filter object.
+ this.command(cmdSetFilter, this._isStateful ? json.toJson(obj) : obj);
+ this.command(cmdClearFilter, null);
+ this.useCommands(true);
+ this.onFilterDefined(filter);
+ }else if(filter === null){
+ this._filter = null;
+ this.command(cmdSetFilter, null);
+ this.command(cmdClearFilter, true);
+ this.useCommands(true);
+ this.onFilterDefined(null);
+ }
+ return this._filter; //_ConditionExpr
+ },
+ onCommandLoad: function(/* (in)string */responce, /* (in|out)keywordArgs */ userRequest){
+ // summary:
+ // override from _ServerSideLayer.onCommandLoad
+ this.inherited(arguments);
+ var oldOnBegin = userRequest.onBegin;
+ if(this._isStateful){
+ var filteredSize;
+ if(responce){
+ this.command(cmdSetFilter, null);
+ this.command(cmdClearFilter, null);
+ this.useCommands(false);
+ var sizes = responce.split(',');
+ if(sizes.length >= 2){
+ filteredSize = this._filteredSize = parseInt(sizes[0], 10);
+ this.onFiltered(filteredSize, parseInt(sizes[1], 10));
+ }else{
+ //Error here.
+ return;
+ }
+ }else{
+ filteredSize = this._filteredSize;
+ }
+ if(this.enabled()){
+ userRequest.onBegin = function(size, req){
+ hitchIfCan(userRequest.scope, oldOnBegin)(filteredSize, req);
+ };
+ }
+ }else{
+ var _this = this;
+ userRequest.onBegin = function(size, req){
+ if(!_this._filter){
+ _this._storeSize = size;
+ }
+ _this.onFiltered(size, _this._storeSize || size);
+ req.onBegin = oldOnBegin;
+ hitchIfCan(userRequest.scope, oldOnBegin)(size, req);
+ };
+ }
+ }
+ });
+ var ClientSideFilterLayer = declare("dojox.grid.enhanced.plugins.filter.ClientSideFilterLayer", [layers._StoreLayer, _FilterLayerMixin], {
+ // summary:
+ // Add a client side filter layer on top of the data store,
+ // so any filter expression can be applied to the store.
+/*=====
+ //_items: Array,
+ // Cached items (may contain holes)
+ _items: [],
+
+ //_result: Array,
+ // Current fetch result
+ _result: [],
+
+ //_resultStartIdx: Integer,
+ // The index in cache of the first result item
+ _resultStartIdx: 0,
+
+ //_indexMap: Array,
+ // A map from the row index of this._items to the row index of the original store.
+ _indexMap: null,
+
+ //_getter: function(datarow, colArg, rowIndex, store);
+ // A user defined way to get data from store
+ _getter: null,
+
+ // _nextUnfetchedIdx: Integer
+ // The index of the next item in the store that is never fetched.
+ _nextUnfetchedIdx: 0,
+=====*/
+ // _storeSize: Integer
+ // The actual size of the original store
+ _storeSize: -1,
+
+ // _fetchAll
+ // If the store is small or store size must be correct when onBegin is called,
+ // we should fetch and filter all the items on the first query.
+ _fetchAll: true,
+
+ constructor: function(args){
+ this.filterDef(null);
+ args = lang.isObject(args) ? args : {};
+ this.fetchAllOnFirstFilter(args.fetchAll);
+ this._getter = lang.isFunction(args.getter) ? args.getter : this._defaultGetter;
+ },
+ _defaultGetter: function(datarow, colName, rowIndex, store){
+ return store.getValue(datarow, colName);
+ },
+ filterDef: function(/* (_ConditionExpr|null)? */filter){
+ // summary:
+ // See _FilterLayerMixin.filterDef
+ if(filter !== undefined){
+ this._filter = filter;
+ this.invalidate();
+ this.onFilterDefined(filter);
+ }
+ return this._filter; //_ConditionExpr
+ },
+ setGetter: function(/* function */getter){
+ // summary:
+ // Set the user defined way to retrieve data from store.
+ // tags:
+ // public
+ // getter: function(datarow, colArg, rowIndex, store);
+ if(lang.isFunction(getter)){
+ this._getter = getter;
+ }
+ },
+ fetchAllOnFirstFilter: function(/* bool? */toFetchAll){
+ // summary:
+ // The get/set function for fetchAll.
+ // tags:
+ // public
+ // toFetchAll: boolean?
+ // If provided, it's a set function, otherwise it's a get function.
+ // returns:
+ // Whether fetch all on first filter if this is a getter
+ if(toFetchAll !== undefined){
+ this._fetchAll = !!toFetchAll;
+ }
+ return this._fetchAll; //Boolean
+ },
+ invalidate: function(){
+ // summary:
+ // Clear all the status information of this layer
+ // tags:
+ // private
+ this._items = [];
+ this._nextUnfetchedIdx = 0;
+ this._result = [];
+ this._indexMap = [];
+ this._resultStartIdx = 0;
+ },
+ //----------------Private Functions-----------------------------
+ _fetch: function(userRequest,filterRequest){
+ // summary:
+ // Implement _StoreLayer._fetch
+ // tags:
+ // private callback
+ // filterRequest: dojo.data.api.Request
+ // The actual request used in store.fetch.
+ // This function is called recursively to fill the result store items
+ // until the user specified item count is reached. Only in recursive calls,
+ // this parameter is valid.
+ if(!this._filter){
+ //If we don't have any filter, use the original request and fetch.
+ var old_onbegin = userRequest.onBegin, _this = this;
+ userRequest.onBegin = function(size, r){
+ hitchIfCan(userRequest.scope, old_onbegin)(size, r);
+ _this.onFiltered(size, size);
+ };
+ this.originFetch(userRequest);
+ return userRequest;
+ }
+ try{
+ //If the fetch is at the beginning, user's start position is used;
+ //If we are in a recursion, our own request is used.
+ var start = filterRequest ? filterRequest._nextResultItemIdx : userRequest.start;
+ start = start || 0;
+ if(!filterRequest){
+ //Initially, we have no results.
+ this._result = [];
+ this._resultStartIdx = start;
+ var sortStr;
+ if(lang.isArray(userRequest.sort) && userRequest.sort.length > 0 &&
+ //Sort info will stay here in every re-fetch, so remember it!
+ (sortStr = json.toJson(userRequest.sort)) != this._lastSortInfo){
+ //If we should sort data, all the old caches are no longer valid.
+ this.invalidate();
+ this._lastSortInfo = sortStr;
+ }
+ }
+ //this._result contains the current fetch result (of every recursion).
+ var end = typeof userRequest.count == "number" ?
+ start + userRequest.count - this._result.length : this._items.length;
+ //Try to retrieve all the items from our cache.
+ //Only need items after userRequest.start, test it in case start is smaller.
+ if(this._result.length){
+ this._result = this._result.concat(this._items.slice(start, end));
+ }else{
+ this._result = this._items.slice(userRequest.start, typeof userRequest.count == "number" ?
+ userRequest.start + userRequest.count : this._items.length);
+ }
+ if(this._result.length >= userRequest.count || this._hasReachedStoreEnd()){
+ //We already have had enough items, or we have to stop fetching because there's nothing more to fetch.
+ this._completeQuery(userRequest);
+ }else{
+ //User's request hasn't been finished yet. Fetch more.
+ if(!filterRequest){
+ //Initially, we've got to create a new request object.
+ filterRequest = shallowClone(userRequest);
+ //Use our own onBegin function to remember the total size of the original store.
+ filterRequest.onBegin = lang.hitch(this, this._onFetchBegin);
+ filterRequest.onComplete = lang.hitch(this, function(items, req){
+ //We've fetched some more, so march ahead!
+ this._nextUnfetchedIdx += items.length;
+ //Actual filtering work goes here. Survived items are added to our cache.
+ //req is our own request object.
+ this._doFilter(items, req.start, userRequest);
+ //Recursively call this function. Let's do this again!
+ this._fetch(userRequest, req);
+ });
+ }
+ //Fetch starts from the next unfetched item.
+ filterRequest.start = this._nextUnfetchedIdx;
+ //If store is small, we should only fetch once.
+ if(this._fetchAll){
+ delete filterRequest.count;
+ }
+ //Remember we've (maybe) already added something to our result array, so next time we should not start over again.
+ filterRequest._nextResultItemIdx = end < this._items.length ? end : this._items.length;
+ //Actual fetch work goes here.
+ this.originFetch(filterRequest);
+ }
+ }catch(e){
+ if(userRequest.onError){
+ hitchIfCan(userRequest.scope, userRequest.onError)(e, userRequest);
+ }else{
+ throw e;
+ }
+ }
+ return userRequest;
+ },
+ _hasReachedStoreEnd: function(){
+ // summary:
+ // Check whether all the items in the original store have been fetched.
+ // tags:
+ // private
+ return this._storeSize >= 0 && this._nextUnfetchedIdx >= this._storeSize; //Boolean
+ },
+ _applyFilter: function(/* data item */datarow,/* Integer */rowIndex){
+ // summary:
+ // Apply the filter to a row of data
+ // tags:
+ // private
+ // returns:
+ // whether this row survived the filter.
+ var g = this._getter, s = this._store;
+ try{
+ return !!(this._filter.applyRow(datarow, function(item, arg){
+ return g(item, arg, rowIndex, s);
+ }).getValue());
+ }catch(e){
+ console.warn("FilterLayer._applyFilter() error: ", e);
+ return false;
+ }
+ },
+ _doFilter: function(/* Array */items,/* Integer */startIdx,/* object */userRequest){
+ // summary:
+ // Use the filter expression to filter items. Survived items are stored in this._items.
+ // The given items start from "startIdx" in the original store.
+ // tags:
+ // private
+ for(var i = 0, cnt = 0; i < items.length; ++i){
+ if(this._applyFilter(items[i], startIdx + i)){
+ hitchIfCan(userRequest.scope, userRequest.onItem)(items[i], userRequest);
+ cnt += this._addCachedItems(items[i], this._items.length);
+ this._indexMap.push(startIdx + i);
+ }
+ }
+ },
+ _onFetchBegin: function(/* Integer */size,/* request object */req){
+ // summary:
+ // This function is used to replace the user's onFetchBegin in store.fetch
+ // tags:
+ // private
+ this._storeSize = size;
+ },
+ _completeQuery: function(/* request object */userRequest){
+ // summary:
+ // Logically, the user's query is completed here, i.e., all the filtered results are ready.
+ // (or their index mappings are ready)
+ // tags:
+ // private
+ var size = this._items.length;
+ if(this._nextUnfetchedIdx < this._storeSize){
+ //FIXME: There's still some items in the original store that are not fetched & filtered.
+ //So we have to estimate a little bigger size to allow scrolling to these unfetched items.
+ //However, this behavior is ONLY correct in Grid! Any better way to do this?
+ size++;
+ }
+ hitchIfCan(userRequest.scope, userRequest.onBegin)(size,userRequest);
+ this.onFiltered(this._items.length, this._storeSize);
+ hitchIfCan(userRequest.scope, userRequest.onComplete)(this._result, userRequest);
+ },
+ _addCachedItems: function(/* Array */items,/* Integer */filterStartIdx){
+ // summary:
+ // Add data items to the cache. The insert point is at *filterStartIdx*
+ // tags:
+ // private
+ // items: Array
+ // Data items to add.
+ // filterStartIdx: Integer
+ // The start point to insert in the cache.
+ if(!lang.isArray(items)){
+ items = [items];
+ }
+ for(var k = 0; k < items.length; ++k){
+ this._items[filterStartIdx + k] = items[k];
+ }
+ return items.length;
+ },
+ onRowMappingChange: function(mapping){
+ //This function runs in FilterLayer scope!
+ if(this._filter){
+ var m = lang.clone(mapping),
+ alreadyUpdated = {};
+ for(var r in m){
+ r = parseInt(r, 10);
+ mapping[this._indexMap[r]] = this._indexMap[m[r]];
+ if(!alreadyUpdated[this._indexMap[r]]){
+ alreadyUpdated[this._indexMap[r]] = true;
+ }
+ if(!alreadyUpdated[r]){
+ alreadyUpdated[r] = true;
+ delete mapping[r];
+ }
+ }
+ }
+ }
+ });
+
+ return lang.mixin({
+ ServerSideFilterLayer: ServerSideFilterLayer,
+ ClientSideFilterLayer: ClientSideFilterLayer
+ }, layers);
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/filter/FilterStatusTip.js b/js/dojo/dojox/grid/enhanced/plugins/filter/FilterStatusTip.js
new file mode 100644
index 0000000..36f4430
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/filter/FilterStatusTip.js
@@ -0,0 +1,148 @@
+//>>built
+define("dojox/grid/enhanced/plugins/filter/FilterStatusTip", [
+ "dojo/_base/declare",
+ "dojo/_base/array",
+ "dojo/_base/lang",
+ "dojo/query",
+ "dojo/cache",
+ "dojo/string",
+ "dojo/date/locale",
+ "dijit/_Widget",
+ "dijit/_TemplatedMixin",
+ "dijit/_WidgetsInTemplateMixin",
+ "dijit/TooltipDialog",
+ "dijit/form/Button",
+ "dijit/_base/popup",
+ "dojo/i18n!../../nls/Filter"
+], function(declare, array, lang, query, cache, string, dateLocale, _Widget,
+ _TemplatedMixin, _WidgetsInTemplateMixin, TooltipDialog, Button, popup){
+
+ var gridCssCls = "", headerCssCls = "", cellCssCls = "", rowCssCls = "",
+ oddRowCssCls = "dojoxGridFStatusTipOddRow",
+ handleHolderCssCls = "dojoxGridFStatusTipHandle",
+ conditionCssCls = "dojoxGridFStatusTipCondition",
+ _removeRuleIconCls = "dojoxGridFStatusTipDelRuleBtnIcon",
+ _statusFooter = "</tbody></table>";
+
+ var FilterStatusPane = declare("dojox.grid.enhanced.plugins.filter.FilterStatusPane", [_Widget, _TemplatedMixin], {
+ templateString: cache("dojox.grid", "enhanced/templates/FilterStatusPane.html")
+ });
+
+ return declare("dojox.grid.enhanced.plugins.filter.FilterStatusTip", null, {
+ // summary:
+ // Create the status tip UI.
+ constructor: function(args){
+ var plugin = this.plugin = args.plugin;
+ this._statusHeader = ["<table border='0' cellspacing='0' class='",
+ gridCssCls, "'><thead><tr class='",
+ headerCssCls, "'><th class='",
+ cellCssCls, "'><div>", plugin.nls["statusTipHeaderColumn"], "</div></th><th class='",
+ cellCssCls, " lastColumn'><div>", plugin.nls["statusTipHeaderCondition"], "</div></th></tr></thead><tbody>"
+ ].join('');
+ this._removedCriterias = [];
+ this._rules = [];
+ this.statusPane = new FilterStatusPane();
+ this._dlg = new TooltipDialog({
+ "class": "dojoxGridFStatusTipDialog",
+ content: this.statusPane,
+ autofocus: false
+ });
+ this._dlg.connect(this._dlg.domNode, 'onmouseleave', lang.hitch(this, this.closeDialog));
+ this._dlg.connect(this._dlg.domNode, 'click', lang.hitch(this, this._modifyFilter));
+ },
+ destroy: function(){
+ this._dlg.destroyRecursive();
+ },
+ //-----------------Public Functions------------------------
+ showDialog: function(/* int */pos_x,/* int */pos_y, columnIdx){
+ this._pos = {x:pos_x,y:pos_y};
+ popup.close(this._dlg);
+ this._removedCriterias = [];
+ this._rules = [];
+ this._updateStatus(columnIdx);
+ popup.open({
+ popup: this._dlg,
+ parent: this.plugin.filterBar,
+ onCancel: function(){},
+ x:pos_x - 12,
+ y:pos_y - 3
+ });
+ },
+ closeDialog: function(){
+ popup.close(this._dlg);
+ if(this._removedCriterias.length){
+ this.plugin.filterDefDialog.removeCriteriaBoxes(this._removedCriterias);
+ this._removedCriterias = [];
+ this.plugin.filterDefDialog.onFilter();
+ }
+ },
+ //-----------------Private Functions---------------------------
+ _updateStatus: function(columnIdx){
+ var res, p = this.plugin,
+ nls = p.nls,
+ sp = this.statusPane,
+ fdg = p.filterDefDialog;
+ if(fdg.getCriteria() === 0){
+ sp.statusTitle.innerHTML = nls["statusTipTitleNoFilter"];
+ sp.statusRel.innerHTML = "";
+ var cell = p.grid.layout.cells[columnIdx];
+ var colName = cell ? "'" + (cell.name || cell.field) + "'" : nls["anycolumn"];
+ res = string.substitute(nls["statusTipMsg"], [colName]);
+ }else{
+ sp.statusTitle.innerHTML = nls["statusTipTitleHasFilter"];
+ sp.statusRel.innerHTML = fdg._relOpCls == "logicall" ? nls["statusTipRelAll"] : nls["statusTipRelAny"];
+ this._rules = [];
+ var i = 0, c = fdg.getCriteria(i++);
+ while(c){
+ c.index = i - 1;
+ this._rules.push(c);
+ c = fdg.getCriteria(i++);
+ }
+ res = this._createStatusDetail();
+ }
+ sp.statusDetailNode.innerHTML = res;
+ this._addButtonForRules();
+ },
+ _createStatusDetail: function(){
+ return this._statusHeader + array.map(this._rules, function(rule, i){
+ return this._getCriteriaStr(rule, i);
+ }, this).join('') + _statusFooter;
+ },
+ _addButtonForRules: function(){
+ if(this._rules.length > 1){
+ query("." + handleHolderCssCls, this.statusPane.statusDetailNode).forEach(lang.hitch(this, function(nd, idx){
+ (new Button({
+ label: this.plugin.nls["removeRuleButton"],
+ showLabel: false,
+ iconClass: _removeRuleIconCls,
+ onClick: lang.hitch(this, function(e){
+ e.stopPropagation();
+ this._removedCriterias.push(this._rules[idx].index);
+ this._rules.splice(idx,1);
+ this.statusPane.statusDetailNode.innerHTML = this._createStatusDetail();
+ this._addButtonForRules();
+ })
+ })).placeAt(nd, "last");
+ }));
+ }
+ },
+ _getCriteriaStr: function(/* object */c, /* int */rowIdx){
+ var res = ["<tr class='", rowCssCls,
+ " ", (rowIdx % 2 ? oddRowCssCls : ""),
+ "'><td class='", cellCssCls, "'>", c.colTxt,
+ "</td><td class='", cellCssCls,
+ "'><div class='", handleHolderCssCls, "'><span class='", conditionCssCls,
+ "'>", c.condTxt, "&nbsp;</span>",
+ c.formattedVal, "</div></td></tr>"];
+ return res.join('');
+ },
+ _modifyFilter: function(){
+ this.closeDialog();
+ var p = this.plugin;
+ p.filterDefDialog.showDialog(p.filterBar.getColumnIdx(this._pos.x));
+ }
+ });
+
+
+ return FilterStatusTip;
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/filter/_ConditionExpr.js b/js/dojo/dojox/grid/enhanced/plugins/filter/_ConditionExpr.js
new file mode 100644
index 0000000..87f3461
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/filter/_ConditionExpr.js
@@ -0,0 +1,243 @@
+//>>built
+define("dojox/grid/enhanced/plugins/filter/_ConditionExpr", [
+ "dojo/_base/declare",
+ "dojo/_base/lang",
+ "dojo/_base/array"
+], function(declare, lang, array){
+
+var _ConditionExpr = declare("dojox.grid.enhanced.plugins.filter._ConditionExpr", null, {
+ // summary:
+ // The most abstract class for all condition expressions.
+ // A condition expression can be applied on a data row (e.g. an item in a store)
+ // and generate a result condition expression.
+ // tags:
+ // abstract
+
+ _name: "expr",
+
+ applyRow: function(/* data item */datarow,/* function(row,colArg) */getter){
+ // summary:
+ // *Unimplemented Interface*
+ // Apply this condition expression on the given datarow, return a result expression.
+ // taqs:
+ // public extension
+ // datarow: object
+ // A data item of a store.
+ // getter: function(datarow, colArg)
+ // A user defined function that extract cell data from *datarow*.
+ // *colArg* is an argument that provides a kind of column information.
+ // It is defined by user in the constructor of a _DataExpr object.
+ // returns:
+ // MUST return a _ConditionExpr object
+ throw new Error("_ConditionExpr.applyRow: unimplemented interface");
+ },
+
+ toObject: function(){
+ // summary:
+ // Convert this data expression to a simple object. Mainly used for serialization.
+ // tags:
+ // public extension
+ // returns:
+ // An object for serialization.
+ return {}; //Object
+ },
+
+ getName: function(){
+ // summary:
+ // Get the name of this kind of expression.
+ // tags:
+ // public extension
+ // returns:
+ // the name of this kind of expression
+ return this._name; //String
+ }
+});
+
+var _DataExpr = declare("dojox.grid.enhanced.plugins.filter._DataExpr", _ConditionExpr, {
+ // summary:
+ // The most abstract class for all data expressions.
+ // A _DataExpr is a condition expression for a single data value.
+ // If the data value to be represent is a pure value (literal value, like string/number/Date/...)
+ // this _DataExpr is nothing more than a simple wrapper.
+ // If the data value to be represent is in a store, then _DataExpr is responsible to extract it
+ // from the store when this condition is applied to a data row.
+ // private fields:
+ // _value: anything
+ // _colArg: anything
+ _name: "data",
+
+ constructor: function(/* anything */dataValue,/* bool */isColumn, /* object */convertArgs){
+ // summary:
+ // If a _DataExpr is constructed with only one argument, this argument is regarded as a pure value.
+ // If the second argument is exactly a boolean true (no implict type transformation,
+ // so as to allow derived classes accept more arguments while retain *isColumn* to be optional),
+ // then this _DataExpr represents a column, and it's applyRow method is not a no-op.
+ // dataValue: anything
+ // If *isColumn* is a boolean true, then it should be a kind of column information, like field name
+ // or column index. Otherwise, it is regarded as a pure value, and the getValue method will simply
+ // return it.
+ // isColumn: boolean?
+ // Optional. To specify whether this _DataExpr represents a column or a pure value.
+ this._convertArgs = convertArgs || {};
+ if(lang.isFunction(this._convertArgs.convert)){
+ this._convertData = lang.hitch(this._convertArgs.scope, this._convertArgs.convert);
+ }
+ if(isColumn){
+ this._colArg = dataValue;
+ }else{
+ this._value = this._convertData(dataValue, this._convertArgs);
+ }
+ },
+
+ getValue: function(){
+ // summary:
+ // If this is a pure value wrapper, simply return the value.
+ // Otherwise (it's a column), return is undefined.
+ // tags:
+ // public
+ // returns:
+ // the value of this data expression.
+ return this._value; //String
+ },
+
+ applyRow: function(/* data item */datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Implement _ConditionExpr.applyRow.
+ // If this is a pure value, simply return self.
+ // Otherwise, extract the cell data from datarow using the given getter function,
+ // and then convert this cell data to a _DataExpr and return the expression.
+ return typeof this._colArg == "undefined" ? this : //_ConditionExpr
+ new (lang.getObject(this.declaredClass))(
+ this._convertData(getter(datarow, this._colArg), this._convertArgs)
+ );
+ },
+
+ _convertData: function(/* anything */dataValue){
+ // summary:
+ //
+ // tags:
+ // protected extension
+ // dataValue: anything
+ // This argument should come from a store.
+ // returns:
+ return dataValue;
+ },
+
+ toObject: function(){
+ // summary:
+ // Overrided from _ConditionExpr.toObject
+ return { //String
+ op: this.getName(),
+ data: this._colArg === undefined ? this._value : this._colArg,
+ isCol: this._colArg !== undefined
+ };
+ }
+});
+
+var _OperatorExpr = declare("dojox.grid.enhanced.plugins.filter._OperatorExpr", _ConditionExpr, {
+ // summary:
+ // The most abstract class for all operator expressions.
+ // An operator expression is a _ConditionExpr that represents an operation.
+ _name: "operator",
+
+ constructor: function(/* Array | operand1,operand2,... */){
+ // summary:
+ // The arguments are operands (or an array of operands, if the first argument
+ // is an Array) of this operator, ordering from left to right.
+ // Every operand should be a _ConditionExpr.
+ if(lang.isArray(arguments[0])){
+ this._operands = arguments[0];
+ }else{
+ this._operands = [];
+ for(var i = 0; i < arguments.length; ++i){
+ this._operands.push(arguments[i]);
+ }
+ }
+ },
+ toObject: function(){
+ // summary:
+ // Overrided from _ConditionExpr.toObject
+ return { //Object
+ op: this.getName(),
+ data: array.map(this._operands,function(operand){
+ return operand.toObject();
+ })
+ };
+ }
+});
+
+var _UniOpExpr = declare("dojox.grid.enhanced.plugins.filter._UniOpExpr", _OperatorExpr, {
+ // summary:
+ // The most abstract class for all uni-operator expressions.
+ // A uni-operator expression is an _OperatorExpr that only allow one operand.
+ _name: "uniOperator",
+
+ applyRow: function(/* data item */datarow,/* function(row,colArg) */getter){
+ // summary:
+ // Implement _ConditionExpr.applyRow.
+ // Apply the restriction of "only one operand" and confirm the operand is a valid _ConditionExpr.
+ // Then do the calculation of this operator.
+ if(!(this._operands[0] instanceof _ConditionExpr)){
+ throw new Error("_UniOpExpr: operand is not expression.");
+ }
+ return this._calculate(this._operands[0],datarow,getter); //_ConditionExpr
+ },
+
+ _calculate: function(/* _ConditionExpr */operand,/* data item*/datarow,/* function(row,colArg) */getter){
+ // summary:
+ // *Unimplemented Interface*
+ // Do the actrual work of applyRow here.
+ // tags:
+ // protected extension
+ // operand: _ConditionExpr
+ // datarow: object
+ // getter: function(row,colArg)
+ // returns:
+ // MUST return a _ConditionExpr object.
+ throw new Error("_UniOpExpr._calculate: unimplemented interface");
+ }
+});
+
+var _BiOpExpr = declare("dojox.grid.enhanced.plugins.filter._BiOpExpr", _OperatorExpr, {
+ // summary:
+ // The most abstract class for all bi-operator expressions.
+ // A bi-operator expression is an _OperatorExpr that allow and only allow two operands.
+ _name: "biOperator",
+
+ applyRow: function(/* data item */datarow,/* function(row,colArg) */getter){
+ // summary:
+ // Implement _ConditionExpr.applyRow.
+ // Apply the restriction of "two operands" and confirm operands are valid _ConditionExpr's.
+ if(!(this._operands[0] instanceof _ConditionExpr)){
+ throw new Error("_BiOpExpr: left operand is not expression.");
+ }else if(!(this._operands[1] instanceof _ConditionExpr)){
+ throw new Error("_BiOpExpr: right operand is not expression.");
+ }
+ return this._calculate(this._operands[0],this._operands[1],datarow,getter);
+ },
+
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,/* data item*/datarow,/* function(row,colArg) */getter){
+ // summary:
+ // *Unimplemented Interface*
+ // Do the actrual work of applyRow here.
+ // tags:
+ // protected extension
+ // left_operand: _ConditionExpr
+ // right_operand: _ConditionExpr
+ // datarow: object
+ // getter: function(row,colArg)
+ // returns:
+ // MUST return a _ConditionExpr object.
+ throw new Error("_BiOpExpr._calculate: unimplemented interface");
+ }
+});
+
+return {
+ _ConditionExpr: _ConditionExpr,
+ _DataExpr: _DataExpr,
+ _OperatorExpr: _OperatorExpr,
+ _UniOpExpr: _UniOpExpr,
+ _BiOpExpr: _BiOpExpr
+};
+
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/filter/_DataExprs.js b/js/dojo/dojox/grid/enhanced/plugins/filter/_DataExprs.js
new file mode 100644
index 0000000..b19c2c4
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/filter/_DataExprs.js
@@ -0,0 +1,85 @@
+//>>built
+define("dojox/grid/enhanced/plugins/filter/_DataExprs", [
+ "dojo/_base/declare",
+ "dojo/_base/lang",
+ "dojo/date/locale",
+ "./_ConditionExpr"
+], function(declare, lang, dateLocale, exprs){
+
+ var BooleanExpr = declare("dojox.grid.enhanced.plugins.filter.BooleanExpr", exprs._DataExpr, {
+ // summary:
+ // A condition expression wrapper for boolean values
+ _name: "bool",
+ _convertData: function(/* anything */dataValue){
+ // summary:
+ // override from _DataExpr
+ return !!dataValue; //Boolean
+ }
+ });
+ var StringExpr = declare("dojox.grid.enhanced.plugins.filter.StringExpr", exprs._DataExpr, {
+ // summary:
+ // A condition expression wrapper for string values
+ _name: "string",
+ _convertData: function(/* anything */dataValue){
+ // summary:
+ // override from _DataExpr
+ return String(dataValue); //String
+ }
+ });
+ var NumberExpr = declare("dojox.grid.enhanced.plugins.filter.NumberExpr", exprs._DataExpr, {
+ // summary:
+ // A condition expression wrapper for number values
+ _name: "number",
+ _convertDataToExpr: function(/* anything */dataValue){
+ // summary:
+ // override from _DataExpr
+ return parseFloat(dataValue); //Number
+ }
+ });
+ var DateExpr = declare("dojox.grid.enhanced.plugins.filter.DateExpr", exprs._DataExpr, {
+ // summary:
+ // A condition expression wrapper for date values
+ _name: "date",
+ _convertData: function(/* anything */dataValue){
+ // summary:
+ // override from _DataExpr
+ if(dataValue instanceof Date){
+ return dataValue;
+ }else if(typeof dataValue == "number"){
+ return new Date(dataValue);
+ }else{
+ var res = dateLocale.parse(String(dataValue), lang.mixin({selector: this._name}, this._convertArgs));
+ if(!res){
+ throw new Error("Datetime parse failed: " + dataValue);
+ }
+ return res;
+ }
+ },
+ toObject: function(){
+ // summary:
+ // Overrided from _DataExpr.toObject
+ if(this._value instanceof Date){
+ var tmp = this._value;
+ this._value = this._value.valueOf();
+ var res = this.inherited(arguments);
+ this._value = tmp;
+ return res;
+ }else{
+ return this.inherited(arguments);
+ }
+ }
+ });
+ var TimeExpr = declare("dojox.grid.enhanced.plugins.filter.TimeExpr", DateExpr, {
+ // summary:
+ // A condition expression wrapper for time values
+ _name: "time"
+ });
+
+ return lang.mixin({
+ BooleanExpr: BooleanExpr,
+ StringExpr: StringExpr,
+ NumberExpr: NumberExpr,
+ DateExpr: DateExpr,
+ TimeExpr: TimeExpr
+ }, exprs);
+});
diff --git a/js/dojo/dojox/grid/enhanced/plugins/filter/_FilterExpr.js b/js/dojo/dojox/grid/enhanced/plugins/filter/_FilterExpr.js
new file mode 100644
index 0000000..f1c2461
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/plugins/filter/_FilterExpr.js
@@ -0,0 +1,248 @@
+//>>built
+define("dojox/grid/enhanced/plugins/filter/_FilterExpr", [
+ "dojo/_base/declare",
+ "dojo/_base/lang",
+ "dojo/date",
+ "./_DataExprs"
+], function(declare, lang, date, exprs){
+//This is the main file that should be 'required' if filter expression facility is necessary.
+
+ /* Logic Operations */
+ var LogicAND = declare("dojox.grid.enhanced.plugins.filter.LogicAND", exprs._BiOpExpr, {
+ // summary:
+ // A logic AND condition expression.
+ _name: "and",
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,
+ /* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var res = left_operand.applyRow(datarow, getter).getValue() &&
+ right_operand.applyRow(datarow, getter).getValue();
+ return new exprs.BooleanExpr(res); //_ConditionExpr
+ }
+ });
+ var LogicOR = declare("dojox.grid.enhanced.plugins.filter.LogicOR", exprs._BiOpExpr, {
+ // summary:
+ // A logic OR condition expression.
+ _name: "or",
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,
+ /* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var res = left_operand.applyRow(datarow, getter).getValue() ||
+ right_operand.applyRow(datarow, getter).getValue();
+ return new exprs.BooleanExpr(res); //_ConditionExpr
+ }
+ });
+ var LogicXOR = declare("dojox.grid.enhanced.plugins.filter.LogicXOR", exprs._BiOpExpr, {
+ // summary:
+ // A logic XOR condition expression.
+ _name: "xor",
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,
+ /* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var left_res = left_operand.applyRow(datarow, getter).getValue();
+ var right_res = right_operand.applyRow(datarow, getter).getValue();
+ return new exprs.BooleanExpr((!!left_res) != (!!right_res)); //_ConditionExpr
+ }
+ });
+ var LogicNOT = declare("dojox.grid.enhanced.plugins.filter.LogicNOT", exprs._UniOpExpr, {
+ // summary:
+ // A logic NOT condition expression.
+ _name: "not",
+ _calculate: function(/* _ConditionExpr */operand,/* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _UniOpExpr
+ return new exprs.BooleanExpr(!operand.applyRow(datarow, getter).getValue()); //_ConditionExpr
+ }
+ });
+ var LogicALL = declare("dojox.grid.enhanced.plugins.filter.LogicALL", exprs._OperatorExpr, {
+ // summary:
+ // A logic ALL condition expression, equals a sequence of logic ANDs
+ _name: "all",
+ applyRow: function(/* data item */datarow,/* function(row,colIdx) */ getter){
+ // summary:
+ // Override from _ConditionExpr
+ for(var i = 0, res = true; res && (this._operands[i] instanceof exprs._ConditionExpr); ++i){
+ res = this._operands[i].applyRow(datarow,getter).getValue();
+ }
+ return new exprs.BooleanExpr(res); //_ConditionExpr
+ }
+ });
+ var LogicANY = declare("dojox.grid.enhanced.plugins.filter.LogicANY", exprs._OperatorExpr, {
+ // summary:
+ // A logic ANY condition expression, equals a sequence of logic ORs
+ _name: "any",
+ applyRow: function(/* data item */datarow,/* function(row,colIdx) */ getter){
+ for(var i = 0,res = false; !res && (this._operands[i] instanceof exprs._ConditionExpr); ++i){
+ res = this._operands[i].applyRow(datarow,getter).getValue();
+ }
+ return new exprs.BooleanExpr(res); //_ConditionExpr
+ }
+ });
+
+ /* Comparison Operations */
+ function compareFunc(left,right,row,getter){
+ left = left.applyRow(row, getter);
+ right = right.applyRow(row, getter);
+ var left_res = left.getValue();
+ var right_res = right.getValue();
+ if(left instanceof exprs.TimeExpr){
+ return date.compare(left_res,right_res,"time");
+ }else if(left instanceof exprs.DateExpr){
+ return date.compare(left_res,right_res,"date");
+ }else{
+ if(left instanceof exprs.StringExpr){
+ left_res = left_res.toLowerCase();
+ right_res = String(right_res).toLowerCase();
+ }
+ return left_res == right_res ? 0 : (left_res < right_res ? -1 : 1);
+ }
+ }
+ var EqualTo = declare("dojox.grid.enhanced.plugins.filter.EqualTo", exprs._BiOpExpr, {
+ // summary:
+ // An "equal to" condition expression.
+ _name: "equal",
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,
+ /* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var res = compareFunc(left_operand,right_operand,datarow,getter);
+ return new exprs.BooleanExpr(res === 0); //_ConditionExpr
+ }
+ });
+ var LessThan = declare("dojox.grid.enhanced.plugins.filter.LessThan", exprs._BiOpExpr, {
+ // summary:
+ // A "less than" condition expression.
+ _name: "less",
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,
+ /* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var res = compareFunc(left_operand,right_operand,datarow,getter);
+ return new exprs.BooleanExpr(res < 0); //_ConditionExpr
+ }
+ });
+ var LessThanOrEqualTo = declare("dojox.grid.enhanced.plugins.filter.LessThanOrEqualTo", exprs._BiOpExpr, {
+ // summary:
+ // A "less than or equal to" condition expression.
+ _name: "lessEqual",
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,
+ /* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var res = compareFunc(left_operand,right_operand,datarow,getter);
+ return new exprs.BooleanExpr(res <= 0); //_ConditionExpr
+ }
+ });
+ var LargerThan = declare("dojox.grid.enhanced.plugins.filter.LargerThan", exprs._BiOpExpr, {
+ // summary:
+ // A "larger than" condition expression.
+ _name: "larger",
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,
+ /* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var res = compareFunc(left_operand,right_operand,datarow,getter);
+ return new exprs.BooleanExpr(res > 0); //_ConditionExpr
+ }
+ });
+ var LargerThanOrEqualTo = declare("dojox.grid.enhanced.plugins.filter.LargerThanOrEqualTo", exprs._BiOpExpr, {
+ // summary:
+ // A "larger than or equal to" condition expression.
+ _name: "largerEqual",
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,
+ /* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var res = compareFunc(left_operand,right_operand,datarow,getter);
+ return new exprs.BooleanExpr(res >= 0); //_ConditionExpr
+ }
+ });
+
+ /* String Operations */
+ var Contains = declare("dojox.grid.enhanced.plugins.filter.Contains", exprs._BiOpExpr, {
+ // summary:
+ // A "contains" condition expression.
+ _name: "contains",
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,
+ /* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var left_res = String(left_operand.applyRow(datarow, getter).getValue()).toLowerCase();
+ var right_res = String(right_operand.applyRow(datarow, getter).getValue()).toLowerCase();
+ return new exprs.BooleanExpr(left_res.indexOf(right_res) >= 0); //_ConditionExpr
+ }
+ });
+ var StartsWith = declare("dojox.grid.enhanced.plugins.filter.StartsWith", exprs._BiOpExpr, {
+ // summary:
+ // A "starts with" condition expression.
+ _name: "startsWith",
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,
+ /* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var left_res = String(left_operand.applyRow(datarow, getter).getValue()).toLowerCase();
+ var right_res = String(right_operand.applyRow(datarow, getter).getValue()).toLowerCase();
+ return new exprs.BooleanExpr(left_res.substring(0, right_res.length) == right_res); //_ConditionExpr
+ }
+ });
+ var EndsWith = declare("dojox.grid.enhanced.plugins.filter.EndsWith", exprs._BiOpExpr, {
+ // summary:
+ // An "ends with" condition expression.
+ _name: "endsWith",
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,
+ /* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var left_res = String(left_operand.applyRow(datarow, getter).getValue()).toLowerCase();
+ var right_res = String(right_operand.applyRow(datarow, getter).getValue()).toLowerCase();
+ return new exprs.BooleanExpr(left_res.substring(left_res.length - right_res.length) == right_res); //_ConditionExpr
+ }
+ });
+ var Matches = declare("dojox.grid.enhanced.plugins.filter.Matches", exprs._BiOpExpr, {
+ // summary:
+ // A "regular expression match" condition expression.
+ // The second operand's value will be regarded as an regular expression string.
+ _name: "matches",
+ _calculate: function(/* _ConditionExpr */left_operand,/* _ConditionExpr */right_operand,
+ /* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var left_res = String(left_operand.applyRow(datarow, getter).getValue());
+ var right_res = new RegExp(right_operand.applyRow(datarow, getter).getValue());
+ return new exprs.BooleanExpr(left_res.search(right_res) >= 0); //_ConditionExpr
+ }
+ });
+ var IsEmpty = declare("dojox.grid.enhanced.plugins.filter.IsEmpty", exprs._UniOpExpr, {
+ // summary:
+ // Check empty
+ _name: "isEmpty",
+ _calculate: function(/* _ConditionExpr */operand,/* data item*/datarow,/* function(row,colIdx) */getter){
+ // summary:
+ // Override from _BiOpExpr
+ var res = operand.applyRow(datarow, getter).getValue();
+ return new exprs.BooleanExpr(res === "" || res == null);
+ }
+ });
+
+ return lang.mixin({
+ LogicAND: LogicAND,
+ LogicOR: LogicOR,
+ LogicXOR: LogicXOR,
+ LogicNOT: LogicNOT,
+ LogicALL: LogicALL,
+ LogicANY: LogicANY,
+ EqualTo: EqualTo,
+ LessThan: LessThan,
+ LessThanOrEqualTo: LessThanOrEqualTo,
+ LargerThan: LargerThan,
+ LargerThanOrEqualTo: LargerThanOrEqualTo,
+ Contains: Contains,
+ StartsWith: StartsWith,
+ EndsWith: EndsWith,
+ Matches: Matches,
+ IsEmpty: IsEmpty
+ }, exprs);
+});
diff --git a/js/dojo/dojox/grid/enhanced/resources/Common.css b/js/dojo/dojox/grid/enhanced/resources/Common.css
new file mode 100644
index 0000000..fc3d346
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/Common.css
@@ -0,0 +1,27 @@
+/* Indirect Selection */
+.dojoxGridRowSelector {
+ cursor: pointer;
+}
+.dojoxGridRowSelectorStatusText{
+ visibility:hidden;
+}
+.dijit_a11y .dojoxGridRowSelected {
+ opacity:0.8 !important;
+}
+.dijit_a11y .dojoxGridBorderDIV {
+ border:2px solid #000 !important;
+}
+.dijit_a11y .dojoxGridRowSelector {
+ height:100% !important;
+}
+.dijit_a11y .dojoxGridRowSelectorStatusText{
+ font-size:larger !important;
+ visibility:visible;
+}
+.dijit_a11y .dijitCheckBox .dojoxGridRowSelectorStatusText{
+ font-weight:bolder !important;
+ font-size:x-large !important;
+}
+.dijit_a11y .dijitCheckBoxChecked .dojoxGridRowSelectorStatusText{
+ font-size:small !important;
+}
diff --git a/js/dojo/dojox/grid/enhanced/resources/Common_rtl.css b/js/dojo/dojox/grid/enhanced/resources/Common_rtl.css
new file mode 100644
index 0000000..796e935
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/Common_rtl.css
@@ -0,0 +1,15 @@
+.dojoxGridRtl .dojoxGridLoading,
+.dojoxGridRtl .dojoxGridError,
+.dojoxGridRtl .dojoxGridNoData {
+ background-position:right;
+ padding-right:25px;
+ padding-left:0px;
+}
+.dojoxGridRtl .dojoxGridHeader {
+ margin-left: 0;
+ margin-right: -1px;
+}
+
+.dojoxGridRtl .dojoxGridCell {
+ text-align: right;
+}
diff --git a/js/dojo/dojox/grid/enhanced/resources/DnD.css b/js/dojo/dojox/grid/enhanced/resources/DnD.css
new file mode 100644
index 0000000..c364b0e
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/DnD.css
@@ -0,0 +1,78 @@
+.dojoxGridBorderDIV {
+ width:2px;
+ background-color: gray;
+ font-size:0em;
+ position:absolute;
+ z-index:9999;
+}
+.dojoxGridCellBorderDIV {
+ position:absolute;
+ background-color: transparent;
+ border: none;
+}
+.dojoxGridCellBorderLeftTopDIV {
+ position: absolute;
+ left: 0;
+ top: 0;
+ border-style: solid;
+ border-width: 2px 0 0 2px;
+ border-color: gray transparent transparent gray;
+}
+.dojoxGridCellBorderRightBottomDIV {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ border-style: solid;
+ border-width: 0 2px 2px 0;
+ border-color: transparent gray gray transparent;
+}
+.dojoxGridDnDItemIcon {
+ background-image: url("images/sprite_icons.png");
+}
+.dojoxGridDnDIconRowSingle {
+ background-position: -256px 5px;
+}
+.dojoxGridDnDIconRowMulti {
+ background-position: -256px -16px;
+}
+.dojoxGridDnDIconColSingle {
+ background-position: -277px 3px;
+}
+.dojoxGridDnDIconColMulti {
+ background-position: -277px -17px;
+}
+.dojoxGridDnDIconCellSingle {
+ background-position: -235px 5px;
+}
+.dojoxGridDnDIconCellMulti {
+ background-position: -236px -16px;
+}
+.dojoxGridDndAvatar {
+ background-color:white;
+ border: 1px solid #CCCCCC;
+ padding: 0px;
+ -moz-box-shadow: 5px 5px 7px #999;
+ -webkit-box-shadow: 5px 5px 7px #999;
+ box-shadow: 5px 5px 7px #999;
+ z-index: 999;
+}
+.dojoxGridDndAvatar td {
+ padding: 3px;
+}
+.dojoxGridDnDIcon,
+.dojoxGridDnDItemIcon {
+ width: 16px;
+ height: 16px;
+}
+.dojoDndMove .dojoxGridDnDIcon {
+ background: url(../../../../dojo/resources/images/dndNoMove.png) no-repeat center center;
+}
+.dojoDndCopy .dojoxGridDnDIcon {
+ background: url(../../../../dojo/resources/images/dndNoCopy.png) no-repeat center center;
+}
+.dojoDndMove .dojoDndAvatarCanDrop .dojoxGridDnDIcon {
+ background: url(../../../../dojo/resources/images/dndMove.png) no-repeat center center;
+}
+.dojoDndCopy .dojoDndAvatarCanDrop .dojoxGridDnDIcon {
+ background: url(../../../../dojo/resources/images/dndCopy.png) no-repeat center center;
+}
diff --git a/js/dojo/dojox/grid/enhanced/resources/DnD_rtl.css b/js/dojo/dojox/grid/enhanced/resources/DnD_rtl.css
new file mode 100644
index 0000000..d7f270f
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/DnD_rtl.css
@@ -0,0 +1,12 @@
+.dojoxGridRtl .dojoxGridCellBorderLeftTopDIV{
+ left: auto;
+ right: 0;
+ border-width: 2px 2px 0 0;
+ border-color: gray gray transparent transparent;
+}
+.dojoxGridRtl .dojoxGridCellBorderRightBottomDIV{
+ right: auto;
+ left: 0;
+ border-width: 0 0 2px 2px;
+ border-color: transparent transparent gray gray;
+}
diff --git a/js/dojo/dojox/grid/enhanced/resources/EnhancedGrid.css b/js/dojo/dojox/grid/enhanced/resources/EnhancedGrid.css
new file mode 100644
index 0000000..7f02773
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/EnhancedGrid.css
@@ -0,0 +1,8 @@
+@import url("Common.css");
+@import url("Filter.css");
+@import url("Pagination.css");
+@import url("DnD.css");
+@import url("Sorter.css");
+@import url("../../../widget/Toaster/Toaster.css");
+@import url("../../../html/resources/ellipsis.css");
+
diff --git a/js/dojo/dojox/grid/enhanced/resources/EnhancedGrid_rtl.css b/js/dojo/dojox/grid/enhanced/resources/EnhancedGrid_rtl.css
new file mode 100644
index 0000000..0aae662
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/EnhancedGrid_rtl.css
@@ -0,0 +1,6 @@
+@import url("../../resources/Grid_rtl.css");
+@import url("Common_rtl.css");
+@import url("Filter_rtl.css");
+@import url("Pagination_rtl.css");
+@import url("DnD_rtl.css");
+@import url("Sorter_rtl.css");
diff --git a/js/dojo/dojox/grid/enhanced/resources/Filter.css b/js/dojo/dojox/grid/enhanced/resources/Filter.css
new file mode 100644
index 0000000..46ca5fe
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/Filter.css
@@ -0,0 +1,292 @@
+/* filter bar */
+.dojoxGridFBar {
+ width: 100%;
+ cursor: pointer;
+}
+.dojoxGridFBar .dojoxGridFBarBtn {
+ margin: 0;
+}
+.dojoxGridFBarBtnTD {
+ width: 38px;
+}
+.dojoxGridFBar .dojoxGridFBarBtn .dijitButtonNode {
+ -moz-border-radius: 1px;
+ -webkit-border-radius: 1px;
+ padding-top: 0;
+ padding-bottom: 0;
+ padding-right: 2px;
+}
+.dojoxGridFBarDefFilterBtnIcon {
+ background: url("images/sprite_icons.png") no-repeat;
+ background-position: -100px -18px;
+ width: 14px;
+ height: 14px;
+}
+.dj_ie .dojoxGridFBarInner{
+ display: inline-block;
+ width: 100%;
+}
+.dojoxGridFBarStatus {
+ margin-left: 9px;
+ float: left;
+}
+.dojoxGridFBarClearFilterBtn {
+ margin: 0 0 0 10px;
+ vertical-align: top;
+ float: left;
+}
+.dojoxGridFBarInfoTD .dojoxGridFBarClearFilterBtn .dijitButtonNode,
+.dojoxGridFBarInfoTD .dojoxGridFBarCloseBtn .dijitButtonNode,
+.dojoxGridFDPane .dijitAccordionTitle .dijitButtonNode,
+.dojoxGridFStatusTipDetail .dijitButton .dijitButtonNode {
+ -moz-border-radius: 0;
+ -moz-box-shadow: none;
+ -webkit-border-radius: 0;
+ -webkit-box-shadow: none;
+ background-image: none;
+ background-color: transparent;
+ margin: 0;
+ padding: 0;
+ border: none;
+}
+.dj_ie .dojoxGridFBarInner {
+ position: relative;
+}
+.dojoxGridFBarCloseBtn {
+ margin: 0 4px 0 0;
+ float: right;
+}
+.dj_ie .dojoxGridFBarCloseBtn {
+ float: none;
+ position: absolute;
+ right: 0;
+}
+.dojoxGridFBarCloseBtnIcon {
+ background: url("images/sprite_icons.png") no-repeat;
+ background-position: -119px -20px;
+ width: 14px;
+ height: 14px;
+}
+.dijitButtonHover .dojoxGridFBarCloseBtnIcon {
+ background-position: -140px -20px;
+}
+.dijitButtonActive .dojoxGridFBarCloseBtnIcon {
+ background-position: -160px -20px;
+}
+
+/* filter def dialog */
+.dojoxGridFDTitlePane {
+ width: 316px;
+ height: 330px;
+}
+.dijit_a11y .dojoxGridFDTitlePane .dijitArrowButtonInner{
+ /* This should be fixed in dijit */
+ display:none !important;
+}
+.dojoxGridFDTitlePane .dijitDialogPaneContent {
+ padding: 7px 5px 9px 5px;
+ height: 290px !important;
+}
+.dojoxGridFDTitlePane .dijitTitlePaneTitle {
+ cursor: move;
+}
+.dojoxGridFDPaneRelation {
+ margin: 0 0 3px 4px;
+}
+.dojoxGridFDPane {
+ width: 100%;
+ height: 100%;
+ position: relative;
+}
+.dojoxGridFDPaneRulePane {
+ height: 222px;
+ overflow: auto;
+ /* for ie6/7 only */
+ position: relative;
+}
+.dj_ie6 .dojoxGridFDPaneRulePane {
+ width: 100%;
+}
+.dojoxGridFDPane .dijitAccordionContainer .dijitContentPane {
+ padding: 6px 9px;
+}
+.dojoxGridFDPane .dijitAccordionTitle {
+ position: relative;
+ /* for non-claro theme, this can ensure a correct height change when adding/removing child */
+ min-height: 17px;
+}
+.dojoxGridFDPane .dijitAccordionTitle .dijitButton {
+ position: absolute;
+ margin: 0;
+ right: 3px;
+ top: 4px;
+}
+.dj_ie6 .dojoxGridFDPane .dijitAccordionTitle .dijitButton {
+ top: 2px;
+}
+.dojoxGridFDPane .dijitAccordionTitleFocus {
+ margin-right: 14px;
+}
+.dojoxGridFDPane .dijitAccordionText {
+ display: inline-block;
+ position: relative;
+}
+.dojoxGridFCBoxRemoveCBoxBtnIcon {
+ background-image: url("images/sprite_icons.png");
+ background-position: -198px -18px;
+ width: 16px;
+ height: 16px;
+}
+.dijitButtonHover .dojoxGridFCBoxRemoveCBoxBtnIcon {
+ background-position: -198px 2px;
+}
+.dojoxGridRuleTitleCondition {
+ font-style: italic;
+}
+.dojoxGridFDPaneModes .dijitSelect {
+ position: relative;
+}
+.dojoxGridFDPaneBtns {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+}
+.dj_ie7 .dojoxGridFDPaneBtns,
+.dj_ie6 .dojoxGridFDPaneBtns {
+ z-index: -1;
+}
+.dojoxGridFDPaneBtns .dijitButton {
+ float: right;
+}
+.dojoxGridFDPaneAddCBoxBtn {
+ margin-top: 9px;
+}
+.dojoxGridFDPaneAddCBoxBtnIcon {
+ background-image: url("images/sprite_icons.png");
+ background-position: -218px 2px;
+ width: 16px;
+ height: 16px;
+}
+.dijitButtonDisabled .dojoxGridFDPaneAddCBoxBtnIcon {
+ background-position: -218px -18px;
+}
+
+/* criteria box */
+.dojoxGridFCBox {
+ height: 125px;
+}
+.dojoxGridFCBoxSelCol,
+.dojoxGridFCBoxCondition {
+ height: 40px;
+}
+.dojoxGridFCBox .dojoxGridFCBoxColSelect,
+.dojoxGridFCBox .dojoxGridFCBoxCondSelect,
+.dojoxGridFCBox .dojoxGridFCBoxValueBox {
+ margin: 0.1em 0 0 0;
+ width: 100%;
+ /* inherited is inline-block this will cause width "error" in non IE for html tables */
+ display: inline-table;
+}
+.dojoxGridFCBoxCondSelectAlt {
+ width: 100%;
+ padding: 5px 0 0 0;
+ font-weight: bold;
+}
+.dojoxGridFCBox .dijitSelect .dijitArrowButton {
+ width: 18px;
+}
+.dojoxGridFCBoxStartValue {
+ width: 45%;
+}
+.dojoxGridFCBoxEndValue {
+ float: right;
+ width: 45%;
+}
+.dojoxGridFCBoxRangeValueTxt {
+ margin-left: 4px;
+}
+
+/* status tip */
+.dojoxGridFStatusTipDialog .dijitTooltipContainer {
+ padding: 9px 5px;
+}
+.dojoxGridFStatusTip thead,
+.dojoxGridFStatusTip tr {
+ height: 19px;
+}
+.dojoxGridFStatusTip th {
+ max-width: 150px;
+ width: expression(this.clientWidth > 150 ? "150px" : "auto");
+}
+.dojoxGridFStatusTip th div {
+ padding: 2px 5px;
+}
+.dojoxGridFStatusTip td {
+ padding: 2px 6px;
+ max-width: 150px;
+ overflow: hidden;
+ width: expression(this.clientWidth > 150 ? "150px" : "auto");
+}
+.dojoxGridFStatusTipHead {
+ margin-bottom: 9px;
+}
+.dojoxGridFStatusTipTitle {
+ font-weight: bold;
+ margin-right: 1em;
+}
+.dojoxGridFStatusTipHandle {
+ position: relative;
+ padding-right: 16px;
+}
+.dojoxGridFStatusTipDetail .dijitButton {
+ position: absolute;
+ margin: 0;
+ padding: 0;
+ top: -1px;
+ right:0;
+}
+.dojoxGridFStatusTipDelRuleBtnIcon {
+ background-image: url("images/sprite_icons.png");
+ background-position: -198px -18px;
+ height: 16px;
+ width: 16px;
+}
+.dijitButtonHover .dojoxGridFStatusTipDelRuleBtnIcon {
+ background-position: -198px 2px;
+}
+
+/* clear dlg */
+.dj_ie7 .dojoxGridClearFilterConfirm,
+.dj_ie6 .dojoxGridClearFilterConfirm {
+ width: 300px;
+}
+.dojoxGridClearFilterBtns{
+ padding: 10px;
+ height: 18px;
+}
+.dojoxGridClearFilterBtns .dijitButton {
+ float: right;
+}
+
+/* bool value box */
+.dojoxGridTrueBox {
+ float: left;
+ width: 49%;
+}
+.dojoxGridFalseBox {
+ float: left;
+ width: 49%;
+}
+.dojoxGridBoolValueBox .dijitRadio {
+ vertical-align: middle;
+}
+.dojoxGridTrueLabel,
+.dojoxGridFalseLabel {
+ width: 116px;
+ display:inline-block;
+ vertical-align: middle;
+}
+.dj_ie7 .dojoxGridTrueLabel,
+.dj_ie7 .dojoxGridFalseLabel {
+ display: inline;
+}
diff --git a/js/dojo/dojox/grid/enhanced/resources/Filter_rtl.css b/js/dojo/dojox/grid/enhanced/resources/Filter_rtl.css
new file mode 100644
index 0000000..c9f2333
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/Filter_rtl.css
@@ -0,0 +1,84 @@
+/* filter bar */
+.dojoxGridRtl .dojoxGridFBarDefFilterBtnIcon {
+ background: url("images/sprite_icons.png") no-repeat;
+ background-position: -180px -18px;
+}
+.dojoxGridRtl .dojoxGridFBarStatus {
+ margin-left: 0;
+ margin-right: 9px;
+ float: right;
+}
+.dojoxGridRtl .dojoxGridFBarClearFilterBtn {
+ margin-left: 0;
+ margin-right: 10px;
+ float: right;
+}
+.dojoxGridRtl .dojoxGridFBarCloseBtn {
+ margin: 0 0 0 4px;
+ float: left;
+}
+.dj_ie .dojoxGridRtl .dojoxGridFBarCloseBtn {
+ left: 2px;
+ right: auto;
+}
+/* filter def dialog */
+.dijitRtl .dojoxGridFDPaneRelation {
+ margin: 0 4px 3px 0;
+}
+.dijitRtl .dojoxGridFDPane .dijitAccordionTitleFocus {
+ margin-right: 0;
+ margin-left: 14px;
+}
+.dijitRtl .dojoxGridFDPane .dijitAccordionTitle .dijitButton {
+ left: 3px;
+ right: auto;
+}
+.dj_ie6 .dijitRtl .dojoxGridFDPane .dijitAccordionTitle .dijitButton{
+ left: -290px;
+}
+.dijitRtl .dojoxGridFDPaneBtns {
+ left: 0;
+ right: auto;
+}
+.dijitRtl .dojoxGridFDPaneBtns .dijitButton,
+.dijitRtl .dojoxGridClearFilterBtns .dijitButton,
+.dijitRtl .dojoxGridFCBoxEndValue {
+ float: left;
+}
+.dijitRtl .dojoxGridFCBoxRangeValueTxt {
+ margin-left: 0;
+ margin-right: 4px;
+}
+
+/* status tip */
+.dijitRtl .dojoxGridFStatusTipTitle {
+ margin-left: 1em;
+ margin-right: 0;
+}
+.dijitRtl .dojoxGridFStatusTipHandle {
+ padding-left: 16px;
+ padding-right: 0;
+}
+.dijitRtl .dojoxGridFStatusTipDetail .dijitButton {
+ left: 0;
+ right: auto;
+}
+
+/* bool value box */
+.dijitRtl .dojoxGridTrueBox,
+.dijitRtl .dojoxGridFalseBox {
+ float: right;
+}
+
+/* For Claro */
+.claro .dojoxGridRtl .dojoxGridFBar {
+ border-right: 1px solid white;
+}
+
+.claro .dijitRtl .dojoxGridFStatusTip th div {
+ border-left: 1px solid #BCBCBC;
+ border-right: 1px solid white;
+}
+.claro .dijitRtl .dojoxGridFStatusTip th.lastColumn div {
+ border-left: 1px solid #BCBCBC;
+}
diff --git a/js/dojo/dojox/grid/enhanced/resources/Pagination.css b/js/dojo/dojox/grid/enhanced/resources/Pagination.css
new file mode 100644
index 0000000..bc1ae55
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/Pagination.css
@@ -0,0 +1,147 @@
+.dojoxGridPaginator {
+ border-top:1px #DBDBDB solid;
+ text-align:center;
+ width: 100%;
+ height: 24px;
+ table-layout : fixed;
+ background-color: #EAEAEA;
+}
+.dojoxGridDescriptionTd {
+ text-align: left;
+ width: 35%;
+}
+.dojoxGridDescription {
+ text-align: left;
+ margin-left: 9px;
+ overflow: hidden;
+}
+.dojoxGridPaginatorFastStep {
+ text-align: right;
+ width: 35%;
+ overflow: hidden;
+}
+.dojoxGridPaginatorStep {
+ float: right;
+}
+.dojoxGridPaginatorGotoTd {
+ width: 20px!important;
+}
+.dojoxGridPaginatorGotoDiv {
+ cursor: pointer;
+ width: 12px!important;
+ height: 16px!important;
+ margin: 0 6px 0 2px;
+ background: url("images/sprite_icons.png") no-repeat -77px 4px;
+}
+.dojoxGridPaginatorGotoDivDisabled {
+ cursor: not-allowed;
+ background: url("images/sprite_icons.png") no-repeat -77px -16px;
+}
+.dojoxGridWardButton {
+ margin-top: 2px;
+ width: 12px!important;
+ height: 12px!important;
+ float: left;
+ background: url("images/sprite_icons.png") no-repeat;
+}
+.dojoxGridWardButtonInner {
+ visibility: hidden;
+}
+.dijit_a11y .dojoxGridWardButtonInner {
+ visibility: visible;
+ margin-bottom: 8px;
+}
+.dojoxGridfirstPageBtn {
+ cursor: pointer;
+ margin-left: 1px;
+ background-position: -57px 3px;
+}
+.dojoxGridfirstPageBtnDisable {
+ margin-left: 1px;
+ cursor: not-allowed;
+ background-position: -57px -17px;
+}
+.dojoxGridprevPageBtn {
+ cursor: pointer;
+ margin: 2px 2px 0 9px;
+ background-position: 3px 3px;
+}
+.dojoxGridprevPageBtnDisable {
+ cursor: not-allowed;
+ margin: 2px 2px 0 9px;
+ background-position: 3px -17px;
+}
+.dojoxGridlastPageBtn {
+ cursor: pointer;
+ margin: 2px 9px 0 9px;
+ background-position: -37px 3px;
+}
+.dojoxGridlastPageBtnDisable {
+ cursor: not-allowed;
+ margin: 2px 9px 0 9px;
+ background-position: -37px -17px;
+}
+
+.dojoxGridnextPageBtn {
+ cursor: pointer;
+ margin-left: 3px;
+ background-position: -17px 3px;
+}
+.dojoxGridnextPageBtnDisable {
+ margin-left: 3px;
+ cursor: not-allowed;
+ background-position: -17px -17px;
+}
+.dojoxGridInactived {
+ font-weight: normal;
+ color: #5D88AF;
+ cursor: pointer;
+ margin: 1px 6px 0 5px;
+ float: left;
+ zoom: 1; /* for IE */
+}
+.dojoxGridActived {
+ font-weight: bold;
+ color: black;
+ margin: 1px 6px 0 5px;
+ float: left;
+ text-decoration: none!important;
+ zoom: 1; /* for IE */
+}
+.dojoxGridInactiveSwitch {
+ font-weight: normal;
+ color: #5D88AF;
+ float: left;
+ cursor: pointer;
+ margin: 1px 7px 0 7px;
+ zoom: 1; /* for IE */
+}
+.dojoxGridActivedSwitch {
+ font-weight: bold;
+ color: black;
+ float: left;
+ margin: 1px 7px 0 7px;
+ text-decoration: none!important;
+ zoom: 1; /* for IE */
+}
+.dojoxGridSeparator {
+ float: left;
+}
+.dojoxGridPageTextHover {
+ text-decoration: underline;
+}
+.dojoxGridDialogMargin {
+ width: 220px!important;
+ margin-bottom: 10px;
+}
+.dj_ie6 .dojoxGridDialogMargin {
+ position: relative;
+}
+.dojoxGridDialogButton {
+ width: 220px!important;
+ text-align: right;
+}
+.dojoxGridButtonFocus {
+ outline: none;
+ border: 0.5px dotted darkblue !important;
+}
diff --git a/js/dojo/dojox/grid/enhanced/resources/Pagination_rtl.css b/js/dojo/dojox/grid/enhanced/resources/Pagination_rtl.css
new file mode 100644
index 0000000..e3a2dd1
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/Pagination_rtl.css
@@ -0,0 +1,68 @@
+.dojoxGridRtl .dojoxGridDescription {
+ text-align: right;
+ margin-right: 9px;
+}
+.dojoxGridRtl .dojoxGridPaginatorStep {
+ float: left;
+}
+.dojoxGridRtl .dojoxGridPaginatorGotoDiv {
+ margin: 0 2px 0 6px;
+}
+.dojoxGridRtl .dojoxGridWardButton {
+ float: right;
+}
+.dojoxGridRtl .dojoxGridInactived {
+ margin: 1px 5px 0 6px;
+ float: right;
+}
+.dojoxGridRtl .dojoxGridActived {
+ margin: 1px 5px 0 6px;
+ float: right;
+}
+.dijitRtl .dojoxGridDialogButton {
+ float: left;
+ margin-bottom: 10px;
+}
+.dijitRtl .dojoxGridInactiveSwitch {
+ float: right;
+}
+.dijitRtl .dojoxGridActivedSwitch {
+ float: right;
+}
+.dijitRtl .dojoxGridSeparator {
+ float: right;
+}
+.dijitRtl .dojoxGridfirstPageBtn {
+ cursor: pointer;
+ margin: 2px 1px 0 0;
+ background-position: -37px 3px;
+}
+.dijitRtl .dojoxGridfirstPageBtnDisable {
+ margin: 2px 1px 0 0;
+ background-position: -37px -17px;
+}
+.dijitRtl .dojoxGridprevPageBtn {
+ cursor: pointer;
+ margin: 2px 9px 0 5px;
+ background-position: -17px 3px;
+}
+.dijitRtl .dojoxGridprevPageBtnDisable {
+ margin: 2px 9px 0 5px;
+ background-position: -17px -17px;
+}
+.dijitRtl .dojoxGridlastPageBtn {
+ cursor: pointer;
+ background-position: -57px 3px;
+}
+.dijitRtl .dojoxGridlastPageBtnDisable {
+ background-position: -57px -17px;
+}
+.dijitRtl .dojoxGridnextPageBtn {
+ cursor: pointer;
+ margin: 2px 3px 0 0;
+ background-position: 3px 3px;
+}
+.dijitRtl .dojoxGridnextPageBtnDisable {
+ margin: 2px 3px 0 0;
+ background-position: 3px -17px;
+} \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/resources/Sorter.css b/js/dojo/dojox/grid/enhanced/resources/Sorter.css
new file mode 100644
index 0000000..11e6fc5
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/Sorter.css
@@ -0,0 +1,179 @@
+/*
+.dojoxGrid
+ Sorted, SingleSorted | NestSorted
+.dojoxGridCell
+ Over, SortFocus, ShowIndex
+.dojoxGridSortNode
+ Asc | Desc, Main|Sub
+.dojoxGridSortBtn
+ :hover, Single|Nested
+*/
+.dojoxGrid .dojoxGridSortNode {
+ position: relative;
+ border: 1px solid transparent;
+ cursor: pointer;
+}
+.dj_ie6 .dojoxGrid .dojoxGridSortNode,
+.dj_ie7 .dojoxGrid .dojoxGridSortNode {
+ overflow: hidden;
+ width:100%;
+}
+.dojoxGrid .dojoxGridSortNoWrap {
+ white-space:nowrap;
+ word-wrap: normal;
+}
+.dojoxGridSortBtn {
+ width: 10px;
+ height:100%;
+ visibility: hidden;
+ top: 0;
+ display:block;
+ position: absolute;
+ color: #000;
+ background: #DFEAF1 url(images/sprite_icons.png) no-repeat 100px 0;
+ text-decoration: none;
+ outline: none;
+ right: 0;
+ border: 1px solid transparent;
+ box-sizing: border-box; /* css3 rec */
+ -moz-box-sizing: border-box; /* ff */
+ -ms-box-sizing: border-box; /* ie8 */
+ -webkit-box-sizing: border-box; /* safari3 */
+ -khtml-box-sizing: border-box; /* konqueror */
+}
+.dj_ie6 .dojoxGridSortBtn,
+.dj_ie6 .dojoxGrid .dojoxGridSortNode {
+ border: none;
+}
+.dojoxGridSortBtnNested {
+ right: 10px;
+}
+.dojoxGridCellSortFocus .dojoxGridSortBtn {
+ border-left: 1px solid #999999;
+ background-color: #DFEAF1;
+}
+.dojoxGridCellOver .dojoxGridSortBtn {
+ border-left: 1px solid #999999;
+ background-color: #9dcfff;
+}
+.dojoxGridSortNode {
+ outline: none;
+}
+
+/*Control the title node width*/
+.dojoxGridSorted .dojoxGridCellOver .dojoxGridSortNode,
+.dojoxGridCellSortFocus .dojoxGridSortNode,
+.dojoxGridSingleSorted .dojoxGridHeader .dojoxGridCellOver .dojoxGridSortNodeMain,
+.dojoxGridSingleSorted .dojoxGridHeader .dojoxGridCellSortFocus .dojoxGridSortNodeMain {
+ margin-right: 5px;
+}
+.dojoxGridSorted .dojoxGridCellOver .dojoxGridSortNode,
+.dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortNode {
+ margin-right: 24px;
+}
+/*html > body used for !dj_ie6, TBD - a better way*/
+html > body .dojoxGridCellOver .dojoxGridSortNode .dojoxGridSortBtnSingle {
+ right: -5px;
+}
+html > body .dojoxGridCellSortFocus .dojoxGridSortNode .dojoxGridSortBtnSingle,
+html > body .dojoxGridSorted .dojoxGridCellOver .dojoxGridSortNodeMain .dojoxGridSortBtnSingle,
+html > body .dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortNodeMain .dojoxGridSortBtnSingle {
+ right: -10px;
+}
+html > body .dojoxGridSorted .dojoxGridCellOver .dojoxGridSortBtnSingle,
+html > body .dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortBtnSingle,
+html > body .dojoxGridNestSorted .dojoxGridCellOver .dojoxGridSortNodeMain .dojoxGridSortBtnSingle,
+html > body .dojoxGridNestSorted .dojoxGridCellSortFocus .dojoxGridSortNodeMain .dojoxGridSortBtnSingle {
+ right: -28px;
+}
+html > body .dojoxGridSorted .dojoxGridCellOver .dojoxGridSortBtnNested,
+html > body .dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortBtnNested {
+ right: -17px;
+}
+
+.dojoxGrid .dojoxGridHeader .dojoxGridRowTable .dojoxGridNoSort .dojoxGridSortNode {
+ margin: 0!important;
+}
+
+.dj_ie7 .dojoxGridSortBtn {
+ right: 0!important;
+}
+.dj_ie7 .dojoxGridSortBtnNested {
+ right: 10px!important;
+}
+
+/*Focus border*/
+/*Control visibility*/
+.dojoxGrid .dojoxGridCellOver .dojoxGridSortNode .dojoxGridSortBtnSingle, /* single sort btn is always visible when mouseover*/
+.dojoxGrid .dojoxGridCellSortFocus .dojoxGridSortNode .dojoxGridSortBtnSingle,
+.dojoxGridSorted .dojoxGridCellOver .dojoxGridSortNode .dojoxGridSortBtnNested, /* in a sorted grid, nest btn is always visible when mouseover (except 1)*/
+.dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortNode .dojoxGridSortBtnNested,
+.dojoxGrid .dojoxGridCellShowIndex .dojoxGridSortNode .dojoxGridSortBtnNested, /* in a single sort grid, when mouseover other columns, show 1 on the main sort column*/
+.dojoxGrid .dojoxGridSortNodeSorted .dojoxGridSortBtn { /* in a sorted column, single or nested sort btn are always visible (except 2)*/
+ visibility: visible;
+}
+.dojoxGridSingleSorted .dojoxGridCellOver .dojoxGridSortNodeMain .dojoxGridSortBtnNested, /*(1)in a single sorted grid, nest btn is hidden in sort column when mouseover*/
+.dojoxGridSingleSorted .dojoxGridCellSortFocus .dojoxGridSortNodeMain .dojoxGridSortBtnNested,
+.dojoxGridSingleSorted .dojoxGridSortNode .dojoxGridSortBtnNested { /*(2)all nested btn is hidden in single sort grid without mouse over*/
+ visibility: hidden;
+}
+
+/*
+-119 asc
+-99 desc
+-159 do asc
+-139 do desc
+-179 no sort
+*/
+/*Control background image*/
+.dojoxGridSortNodeAsc .dojoxGridSortBtnSingle {
+ background-position: -119px 5px;
+ visibility: visible;
+}
+.dojoxGridSortNodeDesc .dojoxGridSortBtnSingle {
+ background-position: -99px 5px;
+ visibility: visible;
+}
+/*hover single sort*/
+.dojoxGridCellOver .dojoxGridSortBtnSingle,
+.dojoxGridCellSortFocus .dojoxGridSortBtnSingle {
+ background-position: -159px 5px;
+}
+.dojoxGridCellOver .dojoxGridSortNodeAsc .dojoxGridSortBtnSingle,
+.dojoxGridCellSortFocus .dojoxGridSortNodeAsc .dojoxGridSortBtnSingle,
+.dojoxGrid .dojoxGridCellOver .dojoxGridSortNode .dojoxGridSortBtnAsc,
+.dojoxGrid .dojoxGridCellSortFocus .dojoxGridSortNode .dojoxGridSortBtnAsc {
+ background-position: -139px 5px;
+}
+.dojoxGridCellOver .dojoxGridSortNodeDesc .dojoxGridSortBtnSingle,
+.dojoxGridCellSortFocus .dojoxGridSortNodeDesc .dojoxGridSortBtnSingle,
+.dojoxGrid .dojoxGridCellOver .dojoxGridSortNode .dojoxGridSortBtnDesc,
+.dojoxGrid .dojoxGridCellSortFocus .dojoxGridSortNode .dojoxGridSortBtnDesc {
+ background-position: -179px 5px;
+}
+/*hover nested sort*/
+.dojoxGridCellOver .dojoxGridSortBtnNested,
+.dojoxGridCellSortFocus .dojoxGridSortBtnNested {
+ background-position: -149px 5px;
+ width: 19px;
+}
+.dojoxGridCellOver .dojoxGridSortNodeAsc .dojoxGridSortBtnNested,
+.dojoxGridCellSortFocus .dojoxGridSortNodeAsc .dojoxGridSortBtnNested {
+ background-position: -129px 5px;
+}
+.dojoxGridCellOver .dojoxGridSortNodeDesc .dojoxGridSortBtnNested,
+.dojoxGridCellSortFocus .dojoxGridSortNodeDesc .dojoxGridSortBtnNested {
+ background-position: -169px 5px;
+}
+.dojoxGridNestSorted .dojoxGridCellOver .dojoxGridSortBtnSingle,
+.dojoxGridNestSorted .dojoxGridCellSortFocus .dojoxGridSortBtnSingle {
+ background-position: -159px 5px;
+}
+.dojoxGridCellOver .dojoxGridSortBtn:hover {
+ background-color:#A3E4FF;
+}
+.dojoxGrid .dojoxGridSortNodeFocus,
+.dojoxGridCellSortFocus .dojoxGridRowSelector,
+.dojoxGridCellSortFocus .dojoxGridSortBtnFocus {
+ border: 1px dashed #666;
+} \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/resources/Sorter_rtl.css b/js/dojo/dojox/grid/enhanced/resources/Sorter_rtl.css
new file mode 100644
index 0000000..3faaedb
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/Sorter_rtl.css
@@ -0,0 +1,78 @@
+.dojoxGridRtl .dojoxGridSortBtnSingle {
+ right: auto;
+ left: 0px;
+}
+.dojoxGridRtl .dojoxGridSortBtnNested {
+ right: auto;
+ left: 10px;
+}
+
+.dojoxGridRtl .dojoxGridCellOver .dojoxGridSortBtn,
+.dj_ie6 dojoxGridRtl .dojoxGridCellOver .dojoxGridSortBtn,
+.dojoxGridRtl .dojoxGridCellSortFocus .dojoxGridSortBtn {
+ border-left: none;
+ border-right: 1px solid #999999;
+}
+
+/*Control the title node width*/
+.dijitRtl .dojoxGridCellOver .dojoxGridSortNode,
+.dijitRtl .dojoxGridCellSortFocus .dojoxGridSortNode,
+.dijitRtl .dojoxGridSingleSorted .dojoxGridHeader .dojoxGridCellOver .dojoxGridSortNodeMain,
+.dijitRtl .dojoxGridSingleSorted .dojoxGridHeader .dojoxGridCellSortFocus .dojoxGridSortNodeMain {
+ margin-right: auto;
+ margin-left: 10px;
+}
+.dijitRtl .dojoxGridSorted .dojoxGridCellOver .dojoxGridSortNode,
+.dijitRtl .dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortNode {
+ margin-right: auto;
+ margin-left: 24px;
+}
+/*html > body used for !dj_ie6, TBD - a better way*/
+html.dijitRtl > body .dojoxGridCellOver .dojoxGridSortNode .dojoxGridSortBtnSingle {
+ right: auto;
+ left: -10px;
+}
+html.dijitRtl > body .dojoxGridCellSortFocus .dojoxGridSortNode .dojoxGridSortBtnSingle,
+html.dijitRtl > body .dojoxGridSorted .dojoxGridCellOver .dojoxGridSortNodeMain .dojoxGridSortBtnSingle,
+html.dijitRtl > body .dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortNodeMain .dojoxGridSortBtnSingle {
+ right: auto;
+ left: -10px;
+}
+html.dijitRtl > body .dojoxGridSorted .dojoxGridCellOver .dojoxGridSortBtnSingle,
+html.dijitRtl > body .dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortBtnSingle,
+html.dijitRtl > body .dojoxGridNestSorted .dojoxGridCellOver .dojoxGridSortNodeMain .dojoxGridSortBtnSingle,
+html.dijitRtl > body .dojoxGridNestSorted .dojoxGridCellSortFocus .dojoxGridSortNodeMain .dojoxGridSortBtnSingle {
+ right: auto;
+ left: -28px;
+}
+html.dijitRtl > body .dojoxGridSorted .dojoxGridCellOver .dojoxGridSortBtnNested,
+html.dijitRtl > body .dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortBtnNested {
+ right: auto;
+ left: -17px;
+}
+.dojoxGridRtl .dojoxGridCellOver .dojoxGridSortBtnNested,
+.dojoxGridRtl .dojoxGridCellSortFocus .dojoxGridSortBtnNested {
+ background-position: -159px 5px;
+ padding-left:8px;
+}
+.dojoxGridRtl .dojoxGridCellOver .dojoxGridSortNodeAsc .dojoxGridSortBtnNested,
+.dojoxGridRtl .dojoxGridCellSortFocus .dojoxGridSortNodeAsc .dojoxGridSortBtnNested {
+ background-position: -139px 5px;
+}
+
+.dojoxGridRtl .dojoxGridCellOver .dojoxGridSortNodeDesc .dojoxGridSortBtnNested,
+.dojoxGridRtl .dojoxGridCellSortFocus .dojoxGridSortNodeDesc .dojoxGridSortBtnNested {
+ background-position: -179px 5px;
+}
+.dojoxGridRtl .dojoxGridCellOver .dojoxGridSortBtnNested,
+.dojoxGridRtl .dojoxGridCellSortFocus .dojoxGridSortBtnNested {
+ padding-left: 8px;
+ padding-right: 0;
+}
+
+.dj_ie6 .dojoxGridRtl .dojoxGridCellOver .dojoxGridSortBtnNested,
+.dj_ie6 .dojoxGridRtl .dojoxGridCellSortFocus .dojoxGridSortBtnNested,
+.dj_ie6 .dojoxGridRtl .dojoxGridCellOver .dojoxGridSortBtnNested,
+.dj_ie6 .dojoxGridRtl .dojoxGridCellSortFocus .dojoxGridSortBtnNested {
+ padding-left:0px;
+}
diff --git a/js/dojo/dojox/grid/enhanced/resources/claro/Common.css b/js/dojo/dojox/grid/enhanced/resources/claro/Common.css
new file mode 100644
index 0000000..cec6c02
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/claro/Common.css
@@ -0,0 +1,26 @@
+.claro .dojoxGridHeader .dojoxGridHeaderActive {
+ background-color:#91c9fe;
+}
+.claro td.dojoxGridRowSelected {
+ border-collapse:separate;
+ background:url("../../../resources/images/row_back.png") #CEE6FA repeat-x;
+}
+.claro .dojoxGridRowOver td.dojoxGridRowSelected {
+ border-top:1px solid #769DC0;
+ border-bottom:1px solid #769DC0;
+}
+.claro .dojoxGridRowActive td.dojoxGridRowSelected {
+ background-image:url("../../../resources/images/td_button_down.png");
+}
+.dj_ie6 .claro .dojoxGridRowOver .dojoxGridCell {
+ border-color: #ABD6FF;
+}
+.dj_ie6 .claro .dojoxGridRowActive .dojoxGridCell {
+ border-color: #7DBEFA;
+}
+
+/* Pagination */
+.claro .dojoxGridPaginator{
+ background: url("../../../resources/images/header_shadow.png") repeat-x scroll center bottom #E5EDF4;
+ /*background-color: #EAF1F6;*/
+}
diff --git a/js/dojo/dojox/grid/enhanced/resources/claro/EnhancedGrid.css b/js/dojo/dojox/grid/enhanced/resources/claro/EnhancedGrid.css
new file mode 100644
index 0000000..5c3b1a6
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/claro/EnhancedGrid.css
@@ -0,0 +1,4 @@
+@import url("../../../resources/claroGrid.css");
+@import url("../EnhancedGrid.css");
+@import url("Common.css");
+@import url("Filter.css");
diff --git a/js/dojo/dojox/grid/enhanced/resources/claro/Filter.css b/js/dojo/dojox/grid/enhanced/resources/claro/Filter.css
new file mode 100644
index 0000000..f2069f6
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/claro/Filter.css
@@ -0,0 +1,58 @@
+.claro .dojoxGridFBarInfoTD {
+ background: url("../../../resources/images/header_shadow.png") #F2F9FF repeat-x bottom;
+ background: -moz-linear-gradient(top, #F2F9FF, #EAF5FF);
+ background: -webkit-gradient(linear, left top, left bottom, from(#F2F9FF), to(#EAF5FF));
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFF2F9FF, endColorstr=#FFEAF5FF);
+}
+.claro .dojoxGridFBarHover .dojoxGridFBarInfoTD {
+ background: url("../../../resources/images/header_shadow.png") #F2F9FF repeat-x bottom;
+ background: -moz-linear-gradient(top, #ECF6FF 2px, #F2F9FF, #EAF5FF 6px);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0.1, #ECF6FF), color-stop(0.6, #F2F9FF), color-stop(0.8, #EAF5FF));
+}
+.dj_gecko .claro .dojoxGridFBarInfoTD,
+.dj_webkit .claro .dojoxGridFBarInfoTD {
+ border-top: 1px solid #BFD6EB;
+ border-bottom: 1px solid #BFD6EB;
+}
+.dj_ie .claro .dojoxGridFBarInner{
+ border-top: 1px solid #BFD6EB;
+ border-bottom: 1px solid #BFD6EB;
+ display:inline-block;
+ width: 100%;
+}
+.claro .dojoxGridFBarClearFilterBtn {
+ color: #5B83B6;
+}
+.claro .dojoxGridFBarInfoTD .dojoxGridFBarClearFilterBtn.dijitButtonHover .dijitButtonText {
+ text-decoration: underline;
+}
+.claro .dojoxGridFBar {
+ border-left: 1px solid white;
+}
+.claro .dojoxGridFStatusTip table {
+ border: 1px solid #BCBCBC;
+}
+.claro .dojoxGridFStatusTip th {
+ background-color: #E8EFF4;
+ border-bottom: 1px solid #BCBCBC;
+}
+.claro .dojoxGridFStatusTip th div {
+ background-color: #E8EFF4;
+ border-left: 1px solid white;
+ border-right: 1px solid #BCBCBC;
+ border-top: 1px solid white;
+ border-bottom: 1px solid white;
+}
+.claro .dojoxGridFStatusTip th.lastColumn div {
+ border-right: 1px solid white;
+}
+.claro .dojoxGridFStatusTip td {
+ border-top: 1px solid white;
+ border-bottom: 1px solid white;
+}
+.claro .dojoxGridFStatusTipCondition {
+ font-style: italic;
+}
+.claro .dojoxGridFStatusTipOddRow {
+ background-color: #F1F8FF;
+}
diff --git a/js/dojo/dojox/grid/enhanced/resources/claroEnhancedGrid.css b/js/dojo/dojox/grid/enhanced/resources/claroEnhancedGrid.css
new file mode 100644
index 0000000..2cbc1de
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/claroEnhancedGrid.css
@@ -0,0 +1,2 @@
+/*backward compatible*/
+@import "claro/EnhancedGrid.css"; \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/resources/images/sprite_icons.png b/js/dojo/dojox/grid/enhanced/resources/images/sprite_icons.png
new file mode 100644
index 0000000..28be879
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/images/sprite_icons.png
Binary files differ
diff --git a/js/dojo/dojox/grid/enhanced/resources/tundra/Common.css b/js/dojo/dojox/grid/enhanced/resources/tundra/Common.css
new file mode 100644
index 0000000..81287aa
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/tundra/Common.css
@@ -0,0 +1,40 @@
+/* overwrite */
+.tundra .dojoxGridHeader .dojoxGridCell{
+ background: #fafafa url(../../../../../dijit/themes/tundra/images/titleBar.png) repeat-x bottom left;
+ border-top: 1px solid #bfbfbf;
+ /*border-left-width: 0px;*/
+}
+.tundra .dojoxGridCell {
+ padding:0px;
+ /*display:inline;*/
+ /*position:relative;*/
+ /*border-left-width: 0px;*/
+}
+.dj_ie6 .tundra .dojoxGridMasterView .dojoxGridCellOver{
+ border: 1px dashed #e9e9e9;
+}
+.dj_ie6 .tundra .dojoxGridHeader .dojoxGridCellOver{
+ border-bottom: none !important;
+ border-right: 1px solid #D5CDB5 !important;
+ border-top: 1px solid #D5CDB5 !important;
+}
+.tundra .dojoxGridRowbarInner {
+ width:20px;
+}
+.tundra .dojoxGridCellOver .dojoxGridSortNode,
+.tundra .dojoxGridCellSortFocus .dojoxGridSortNode {
+ cursor:pointer;
+ background: #f8fafd url("../../../../../dijit/themes/tundra/images/accordionItemHover.gif") bottom repeat-x;
+}
+/* end overwrite */
+
+/* fix safari focus border - overwrite */
+.dj_webkit .tundra .dojoxGridCell,
+.dj_webkit .tundra .dojoxGridCellFocus {
+ outline: none;
+}
+
+/*Pagination*/
+.tundra .dojoxGridPaginator {
+ background: url("../../../../../dijit/themes/tundra/images/titleBar.png") repeat-x top left;
+}
diff --git a/js/dojo/dojox/grid/enhanced/resources/tundra/EnhancedGrid.css b/js/dojo/dojox/grid/enhanced/resources/tundra/EnhancedGrid.css
new file mode 100644
index 0000000..f8159c8
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/tundra/EnhancedGrid.css
@@ -0,0 +1,5 @@
+@import url("../../../resources/tundraGrid.css");
+@import url("../EnhancedGrid.css");
+@import url("Common.css");
+@import url("Filter.css");
+@import url("Sorter.css");
diff --git a/js/dojo/dojox/grid/enhanced/resources/tundra/Filter.css b/js/dojo/dojox/grid/enhanced/resources/tundra/Filter.css
new file mode 100644
index 0000000..b7b7b83
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/tundra/Filter.css
@@ -0,0 +1,38 @@
+.tundra .dojoxGridFBar {
+ background-color: #eeeeee;
+ border: 1px solid #bfbfbf;
+}
+.tundra .dojoxGridFBarFiltered {
+ background: #fafafa url(../../../../../dijit/themes/tundra/images/titleBar.png) repeat-x bottom left;
+}
+.tundra .dojoxGridFBarHover {
+ background-color: #cccccc;
+ background-image: none;
+}
+.tundra .dojoxGridFStatusTip table {
+ border: 1px solid #eeeeee;
+}
+.tundra .dojoxGridFStatusTip th {
+ background: #fafafa url(../../../../../dijit/themes/tundra/images/titleBar.png) repeat-x bottom left;
+ border-bottom: 1px solid #eeeeee;
+}
+.tundra .dojoxGridFStatusTip th div {
+ border-left: 1px solid white;
+ border-right: 1px solid #eeeeee;
+ border-top: 1px solid white;
+ border-bottom: 1px solid white;
+}
+.tundra .dojoxGridFStatusTip th.lastColumn div {
+ border-right: 1px solid white;
+}
+.tundra .dojoxGridFStatusTip td {
+ border-top: 1px solid white;
+ border-bottom: 1px solid white;
+}
+.tundra .dojoxGridFStatusTipRel,
+.tundra .dojoxGridFStatusTipCondition {
+ font-style: italic;
+}
+.tundra .dojoxGridFStatusTipOddRow {
+ background-color: #f2f5f9;
+}
diff --git a/js/dojo/dojox/grid/enhanced/resources/tundra/Sorter.css b/js/dojo/dojox/grid/enhanced/resources/tundra/Sorter.css
new file mode 100644
index 0000000..480dd7e
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/tundra/Sorter.css
@@ -0,0 +1,83 @@
+.tundra .dojoxGridSortBtn {
+ padding-top: 3px;
+}
+.tundra .dojoxGridSortBtnNested {
+ right: 11px;
+}
+.tundra .dojoxGridCellOver .dojoxGridSortBtn,
+.tundra .dojoxGridCellSortFocus .dojoxGridSortBtn {
+ background-color: #ccc;
+}
+
+/*Control the title node width*/
+.tundra .dojoxGridCellOver .dojoxGridSortNode,
+.tundra .dojoxGridCellSortFocus .dojoxGridSortNode,
+.tundra .dojoxGridSingleSorted .dojoxGridHeader .dojoxGridCellOver .dojoxGridSortNodeMain,
+.tundra .dojoxGridSingleSorted .dojoxGridHeader .dojoxGridCellSortFocus .dojoxGridSortNodeMain {
+ margin-right: 12px;
+}
+.tundra .dojoxGridSorted .dojoxGridCellOver .dojoxGridSortNode,
+.tundra .dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortNode {
+ margin-right: 31px;
+}
+
+/*ie 6 doesn't need below*/
+.tundra .dojoxGridCellOver .dojoxGridSortNode .dojoxGridSortBtnSingle,
+.tundra .dojoxGridCellSortFocus .dojoxGridSortNode .dojoxGridSortBtnSingle,
+.tundra .dojoxGridSorted .dojoxGridCellOver .dojoxGridSortNodeMain .dojoxGridSortBtnSingle,
+.tundra .dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortNodeMain .dojoxGridSortBtnSingle {
+ right: -12px;
+}
+.tundra .dojoxGridSorted .dojoxGridCellOver .dojoxGridSortBtnSingle,
+.tundra .dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortBtnSingle,
+.tundra .dojoxGridNestSorted .dojoxGridCellOver .dojoxGridSortNodeMain .dojoxGridSortBtnSingle,
+.tundra .dojoxGridNestSorted .dojoxGridCellSortFocus .dojoxGridSortNodeMain .dojoxGridSortBtnSingle {
+ right: -31px;
+}
+.tundra .dojoxGridSorted .dojoxGridCellOver .dojoxGridSortBtnNested,
+.tundra .dojoxGridSorted .dojoxGridCellSortFocus .dojoxGridSortBtnNested {
+ right: -20px;
+}
+/*ie6 hack end*/
+
+/*Control background image*/
+.tundra .dojoxGridSortNodeAsc .dojoxGridSortBtnSingle {
+ background-position: -119px 8px;
+}
+.tundra .dojoxGridSortNodeDesc .dojoxGridSortBtnSingle {
+ background-position: -99px 8px;
+}
+/*hover single sort*/
+.tundra .dojoxGridCellOver .dojoxGridSortBtnSingle,
+.tundra .dojoxGridCellSortFocus .dojoxGridSortBtnSingle {
+ background-position: -159px 8px;
+}
+.tundra .dojoxGridCellOver .dojoxGridSortNodeAsc .dojoxGridSortBtnSingle,
+.tundra .dojoxGridCellSortFocus .dojoxGridSortNodeAsc .dojoxGridSortBtnSingle,
+.tundra .dojoxGrid .dojoxGridCellOver .dojoxGridSortNode .dojoxGridSortBtnAsc,
+.tundra .dojoxGrid .dojoxGridCellSortFocus .dojoxGridSortNode .dojoxGridSortBtnAsc {
+ background-position: -139px 8px;
+}
+.tundra .dojoxGridCellOver .dojoxGridSortNodeDesc .dojoxGridSortBtnSingle,
+.tundra .dojoxGridCellSortFocus .dojoxGridSortNodeDesc .dojoxGridSortBtnSingle,
+.tundra .dojoxGrid .dojoxGridCellOver .dojoxGridSortNode .dojoxGridSortBtnDesc,
+.tundra .dojoxGrid .dojoxGridCellSortFocus .dojoxGridSortNode .dojoxGridSortBtnDesc {
+ background-position: -179px 8px;
+}
+/*hover nested sort*/
+.tundra .dojoxGridCellOver .dojoxGridSortBtnNested,
+.tundra .dojoxGridCellSortFocus .dojoxGridSortBtnNested {
+ background-position: -150px 8px;
+}
+.tundra .dojoxGridCellOver .dojoxGridSortNodeAsc .dojoxGridSortBtnNested,
+.tundra .dojoxGridCellSortFocus .dojoxGridSortNodeAsc .dojoxGridSortBtnNested {
+ background-position: -130px 8px;
+}
+.tundra .dojoxGridCellOver .dojoxGridSortNodeDesc .dojoxGridSortBtnNested,
+.tundra .dojoxGridCellSortFocus .dojoxGridSortNodeDesc .dojoxGridSortBtnNested {
+ background-position: -170px 8px;
+}
+.tundra .dojoxGridNestSorted .dojoxGridCellOver .dojoxGridSortBtnSingle,
+.tundra .dojoxGridNestSorted .dojoxGridCellSortFocus .dojoxGridSortBtnSingle {
+ background-position: -159px 8px;
+} \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/resources/tundraEnhancedGrid.css b/js/dojo/dojox/grid/enhanced/resources/tundraEnhancedGrid.css
new file mode 100644
index 0000000..a770d0c
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/resources/tundraEnhancedGrid.css
@@ -0,0 +1,2 @@
+/*backward compatible*/
+@import "tundra/EnhancedGrid.css"; \ No newline at end of file
diff --git a/js/dojo/dojox/grid/enhanced/templates/ClearFilterConfirmPane.html b/js/dojo/dojox/grid/enhanced/templates/ClearFilterConfirmPane.html
new file mode 100644
index 0000000..1637b2e
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/templates/ClearFilterConfirmPane.html
@@ -0,0 +1,9 @@
+<div class="dojoxGridClearFilterConfirm">
+ <div class="dojoxGridClearFilterMsg">
+ ${_clearFilterMsg}
+ </div>
+ <div class="dojoxGridClearFilterBtns" dojoAttachPoint="btnsNode">
+ <span dojoType="dijit.form.Button" label="${_cancelBtnLabel}" dojoAttachPoint="cancelBtn" dojoAttachEvent="onClick:_onCancel"></span>
+ <span dojoType="dijit.form.Button" label="${_clearBtnLabel}" dojoAttachPoint="clearBtn" dojoAttachEvent="onClick:_onClear"></span>
+ </div>
+</div>
diff --git a/js/dojo/dojox/grid/enhanced/templates/CriteriaBox.html b/js/dojo/dojox/grid/enhanced/templates/CriteriaBox.html
new file mode 100644
index 0000000..ad9a1ec
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/templates/CriteriaBox.html
@@ -0,0 +1,20 @@
+<div class="dojoxGridFCBox">
+ <div class="dojoxGridFCBoxSelCol" dojoAttachPoint="selColNode">
+ <span class="dojoxGridFCBoxField">${_colSelectLabel}</span>
+ <select dojoAttachPoint="_colSelect" dojoType="dijit.form.Select"
+ class="dojoxGridFCBoxColSelect"
+ dojoAttachEvent="onChange:_onChangeColumn">
+ </select>
+ </div>
+ <div class="dojoxGridFCBoxCondition" dojoAttachPoint="condNode">
+ <span class="dojoxGridFCBoxField">${_condSelectLabel}</span>
+ <select dojoAttachPoint="_condSelect" dojoType="dijit.form.Select"
+ class="dojoxGridFCBoxCondSelect"
+ dojoAttachEvent="onChange:_onChangeCondition">
+ </select>
+ <div class="dojoxGridFCBoxCondSelectAlt" dojoAttachPoint="_condSelectAlt" style="display:none;"></div>
+ </div>
+ <div class="dojoxGridFCBoxValue" dojoAttachPoint="valueNode">
+ <span class="dojoxGridFCBoxField">${_valueBoxLabel}</span>
+ </div>
+</div>
diff --git a/js/dojo/dojox/grid/enhanced/templates/FilterBar.html b/js/dojo/dojox/grid/enhanced/templates/FilterBar.html
new file mode 100644
index 0000000..cbcb68d
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/templates/FilterBar.html
@@ -0,0 +1,15 @@
+<table class="dojoxGridFBar" border="0" cellspacing="0" dojoAttachEvent="onclick:_onClickFilterBar, onmouseenter:_onMouseEnter, onmouseleave:_onMouseLeave, onmousemove:_onMouseMove"
+ ><tr><td class="dojoxGridFBarBtnTD"
+ ><span dojoType="dijit.form.Button" class="dojoxGridFBarBtn" dojoAttachPoint="defineFilterButton" label="..." iconClass="dojoxGridFBarDefFilterBtnIcon" showLabel="true" dojoAttachEvent="onClick:_showFilterDefDialog, onMouseEnter:_onEnterButton, onMouseLeave:_onLeaveButton, onMouseMove:_onMoveButton"></span
+ ></td><td class="dojoxGridFBarInfoTD"
+ ><span class="dojoxGridFBarInner"
+ ><span class="dojoxGridFBarStatus" dojoAttachPoint="statusBarNode">${_noFilterMsg}</span
+ ><span dojoType="dijit.form.Button" class="dojoxGridFBarClearFilterBtn" dojoAttachPoint="clearFilterButton"
+ label="${_filterBarClearBtnLabel}" iconClass="dojoxGridFBarClearFilterBtnIcon" showLabel="true"
+ dojoAttachEvent="onClick:_clearFilterDefDialog, onMouseEnter:_onEnterButton, onMouseLeave:_onLeaveButton, onMouseMove:_onMoveButton"></span
+ ><span dojotype="dijit.form.Button" class="dojoxGridFBarCloseBtn" dojoAttachPoint="closeFilterBarButton"
+ label="${_closeFilterBarBtnLabel}" iconClass="dojoxGridFBarCloseBtnIcon" showLabel="false"
+ dojoAttachEvent="onClick:_closeFilterBar, onMouseEnter:_onEnterButton, onMouseLeave:_onLeaveButton, onMouseMove:_onMoveButton"></span
+ ></span
+ ></td></tr
+></table>
diff --git a/js/dojo/dojox/grid/enhanced/templates/FilterBoolValueBox.html b/js/dojo/dojox/grid/enhanced/templates/FilterBoolValueBox.html
new file mode 100644
index 0000000..6779e70
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/templates/FilterBoolValueBox.html
@@ -0,0 +1,11 @@
+<div class="dojoxGridBoolValueBox">
+ <div class="dojoxGridTrueBox">
+ <input dojoType="dijit.form.RadioButton" type='radio' name='a1' id='${_baseId}_rbTrue' checked="true"
+ dojoAttachPoint="rbTrue" dojoAttachEvent="onChange: onChange"/>
+ <div class="dojoxGridTrueLabel" for='${_baseId}_rbTrue'>${_lblTrue}</div>
+ </div>
+ <div class="dojoxGridFalseBox">
+ <input dojoType="dijit.form.RadioButton" dojoAttachPoint="rbFalse" type='radio' name='a1' id='${_baseId}_rbFalse'/>
+ <div class="dojoxGridTrueLabel" for='${_baseId}_rbFalse'>${_lblFalse}</div>
+ </div>
+</div>
diff --git a/js/dojo/dojox/grid/enhanced/templates/FilterDefPane.html b/js/dojo/dojox/grid/enhanced/templates/FilterDefPane.html
new file mode 100644
index 0000000..5783f36
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/templates/FilterDefPane.html
@@ -0,0 +1,27 @@
+<div class="dojoxGridFDPane">
+ <div class="dojoxGridFDPaneRelation">${_relMsgFront}
+ <span class="dojoxGridFDPaneModes" dojoAttachPoint="criteriaModeNode">
+ <select dojoAttachPoint="_relSelect" dojoType="dijit.form.Select" dojoAttachEvent="onChange: _onRelSelectChange">
+ <option value="0">${_relAll}</option>
+ <option value="1">${_relAny}</option>
+ </select>
+ </span>
+ ${_relMsgTail}
+ </div>
+ <div dojoAttachPoint="criteriaPane" class="dojoxGridFDPaneRulePane"></div>
+ <div dojoAttachPoint="_addCBoxBtn" dojoType="dijit.form.Button"
+ class="dojoxGridFDPaneAddCBoxBtn" iconClass="dojoxGridFDPaneAddCBoxBtnIcon"
+ dojoAttachEvent="onClick:_onAddCBox" label="${_addRuleBtnLabel}" showLabel="false">
+ </div>
+ <div class="dojoxGridFDPaneBtns" dojoAttachPoint="buttonsPane">
+ <span dojoAttachPoint="_cancelBtn" dojoType="dijit.form.Button"
+ dojoAttachEvent="onClick:_onCancel" label="${_cancelBtnLabel}">
+ </span>
+ <span dojoAttachPoint="_clearFilterBtn" dojoType="dijit.form.Button"
+ dojoAttachEvent="onClick:_onClearFilter" label="${_clearBtnLabel}" disabled="true">
+ </span>
+ <span dojoAttachPoint="_filterBtn" dojoType="dijit.form.Button"
+ dojoAttachEvent="onClick:_onFilter" label="${_filterBtnLabel}" disabled="true">
+ </span>
+ </div>
+</div>
diff --git a/js/dojo/dojox/grid/enhanced/templates/FilterStatusPane.html b/js/dojo/dojox/grid/enhanced/templates/FilterStatusPane.html
new file mode 100644
index 0000000..67be8d4
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/templates/FilterStatusPane.html
@@ -0,0 +1,8 @@
+<div class="dojoxGridFStatusTip"
+ ><div class="dojoxGridFStatusTipHead"
+ ><span class="dojoxGridFStatusTipTitle" dojoAttachPoint="statusTitle"></span
+ ><span class="dojoxGridFStatusTipRel" dojoAttachPoint="statusRel"></span
+ ></div
+ ><div class="dojoxGridFStatusTipDetail" dojoAttachPoint="statusDetailNode"
+ ></div
+></div>
diff --git a/js/dojo/dojox/grid/enhanced/templates/Pagination.html b/js/dojo/dojox/grid/enhanced/templates/Pagination.html
new file mode 100644
index 0000000..ad55539
--- /dev/null
+++ b/js/dojo/dojox/grid/enhanced/templates/Pagination.html
@@ -0,0 +1,18 @@
+<div dojoAttachPoint="paginatorBar"
+ ><table cellpadding="0" cellspacing="0" class="dojoxGridPaginator"
+ ><tr
+ ><td dojoAttachPoint="descriptionTd" class="dojoxGridDescriptionTd"
+ ><div dojoAttachPoint="descriptionDiv" class="dojoxGridDescription"></div
+ ></div></td
+ ><td dojoAttachPoint="sizeSwitchTd"></td
+ ><td dojoAttachPoint="pageStepperTd" class="dojoxGridPaginatorFastStep"
+ ><div dojoAttachPoint="pageStepperDiv" class="dojoxGridPaginatorStep"></div
+ ></td
+ ><td dojoAttachPoint="gotoPageTd" class="dojoxGridPaginatorGotoTd"
+ ><div dojoAttachPoint="gotoPageDiv" class="dojoxGridPaginatorGotoDiv" dojoAttachEvent="onclick:_openGotopageDialog, onkeydown:_openGotopageDialog"
+ ><span class="dojoxGridWardButtonInner">&#8869;</span
+ ></div
+ ></td
+ ></tr
+ ></table
+></div>