diff options
| author | Tristan Zur <tzur@web.web.ccwn.org> | 2014-03-27 22:27:47 +0100 |
|---|---|---|
| committer | Tristan Zur <tzur@web.web.ccwn.org> | 2014-03-27 22:27:47 +0100 |
| commit | b62676ca5d3d6f6ba3f019ea3f99722e165a98d8 (patch) | |
| tree | 86722cb80f07d4569f90088eeaea2fc2f6e2ef94 /js/dojo-1.6/dojox/grid/enhanced/plugins | |
Diffstat (limited to 'js/dojo-1.6/dojox/grid/enhanced/plugins')
62 files changed, 23319 insertions, 0 deletions
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/AutoScroll.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/AutoScroll.js new file mode 100644 index 0000000..a64128f --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/AutoScroll.js @@ -0,0 +1,182 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.AutoScroll"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.AutoScroll"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.AutoScroll");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid._RowSelector");
+
+dojo.declare("dojox.grid.enhanced.plugins.AutoScroll", dojox.grid.enhanced._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 = dojo.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(dojo.doc, "onmouseup", function(evt){
+ this._manageAutoScroll(true);
+ this.readyForAutoScroll = false;
+ });
+ this.connect(dojo.doc, "onmousemove", function(evt){
+ if(this.readyForAutoScroll){
+ this._event = evt;
+ var gridPos = dojo.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 = dojo.some(g.views.views, function(view, i){
+ if(view instanceof dojox.grid._RowSelector){
+ return false;
+ }
+ var viewPos = dojo.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(dojo.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 = dojo.filter(this.grid.layout.cells, function(cell){
+ return !cell.hidden;
+ });
+ var viewPos = dojo.position(view.domNode);
+ var limit, edge, headerPos, i;
+ if(isForward){
+ limit = node.clientWidth;
+ for(i = 0; i < cells.length; ++i){
+ headerPos = dojo.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 = dojo.position(cells[i].getHeaderNode());
+ edge = headerPos.x - viewPos.x;
+ if(edge < limit){
+ target = cells[i].index;
+ node.scrollLeft += edge - limit - 10;
+ break;
+ }
+ }
+ }
+ }
+ return target;
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.AutoScroll/*name:'autoScroll'*/);
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/AutoScroll.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/AutoScroll.xd.js new file mode 100644 index 0000000..0afebe6 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/AutoScroll.xd.js @@ -0,0 +1,188 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.AutoScroll"],
+["require", "dojox.grid.enhanced._Plugin"],
+["require", "dojox.grid._RowSelector"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.AutoScroll"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.AutoScroll"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.AutoScroll");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid._RowSelector");
+
+dojo.declare("dojox.grid.enhanced.plugins.AutoScroll", dojox.grid.enhanced._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 = dojo.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(dojo.doc, "onmouseup", function(evt){
+ this._manageAutoScroll(true);
+ this.readyForAutoScroll = false;
+ });
+ this.connect(dojo.doc, "onmousemove", function(evt){
+ if(this.readyForAutoScroll){
+ this._event = evt;
+ var gridPos = dojo.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 = dojo.some(g.views.views, function(view, i){
+ if(view instanceof dojox.grid._RowSelector){
+ return false;
+ }
+ var viewPos = dojo.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(dojo.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 = dojo.filter(this.grid.layout.cells, function(cell){
+ return !cell.hidden;
+ });
+ var viewPos = dojo.position(view.domNode);
+ var limit, edge, headerPos, i;
+ if(isForward){
+ limit = node.clientWidth;
+ for(i = 0; i < cells.length; ++i){
+ headerPos = dojo.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 = dojo.position(cells[i].getHeaderNode());
+ edge = headerPos.x - viewPos.x;
+ if(edge < limit){
+ target = cells[i].index;
+ node.scrollLeft += edge - limit - 10;
+ break;
+ }
+ }
+ }
+ }
+ return target;
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.AutoScroll/*name:'autoScroll'*/);
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/CellMerge.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/CellMerge.js new file mode 100644 index 0000000..1bfb408 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/CellMerge.js @@ -0,0 +1,277 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.CellMerge"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.CellMerge"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.CellMerge");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+
+dojo.declare("dojox.grid.enhanced.plugins.CellMerge", dojox.grid.enhanced._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 && dojo.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 = dojo.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){
+ dojo.forEach(config, this._createRecord, this);
+ },
+ _initEvents: function(){
+ dojo.forEach(this.grid.views.views, function(view){
+ this.connect(view, "onAfterRow", dojo.hitch(this, "_onAfterRow", view.index));
+ }, this);
+ },
+ _mixinGrid: function(){
+ var g = this.grid;
+ g.mergeCells = dojo.hitch(this, "mergeCells");
+ g.unmergeCells = dojo.hitch(this, "unmergeCells");
+ g.getMergedCells = dojo.hitch(this, "getMergedCells");
+ g.getMergedCellsByRow = dojo.hitch(this, "getMergedCellsByRow");
+ },
+ _getWidth: function(colIndex){
+ var node = this.grid.layout.cells[colIndex].getHeaderNode();
+ return dojo.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] = [];
+ dojo.forEach(result, function(res){
+ dojo.forEach(res.hiddenCells, function(node){
+ dojo.style(node, "display", "none");
+ });
+ var pbm = dojo.marginBox(res.majorHeaderNode).w - dojo.contentBox(res.majorHeaderNode).w;
+ var tw = res.totalWidth;
+
+ //Tricky for WebKit.
+ if(!dojo.isWebKit){
+ tw -= pbm;
+ }
+
+ dojo.style(res.majorNode, "width", tw + "px");
+ //In case we're dealing with multiple subrows.
+ dojo.attr(res.majorNode, "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(dojo.isFunction(item.row)){
+ this._records.push(item);
+ return item;
+ }
+ }
+ return null;
+ },
+ _isValid: function(item){
+ var cells = this.grid.layout.cells,
+ colCount = cells.length;
+ return (dojo.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);
+ }
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.CellMerge/*name:'cellMerge'*/);
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/CellMerge.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/CellMerge.xd.js new file mode 100644 index 0000000..72e7f15 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/CellMerge.xd.js @@ -0,0 +1,282 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.CellMerge"],
+["require", "dojox.grid.enhanced._Plugin"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.CellMerge"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.CellMerge"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.CellMerge");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+
+dojo.declare("dojox.grid.enhanced.plugins.CellMerge", dojox.grid.enhanced._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 && dojo.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 = dojo.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){
+ dojo.forEach(config, this._createRecord, this);
+ },
+ _initEvents: function(){
+ dojo.forEach(this.grid.views.views, function(view){
+ this.connect(view, "onAfterRow", dojo.hitch(this, "_onAfterRow", view.index));
+ }, this);
+ },
+ _mixinGrid: function(){
+ var g = this.grid;
+ g.mergeCells = dojo.hitch(this, "mergeCells");
+ g.unmergeCells = dojo.hitch(this, "unmergeCells");
+ g.getMergedCells = dojo.hitch(this, "getMergedCells");
+ g.getMergedCellsByRow = dojo.hitch(this, "getMergedCellsByRow");
+ },
+ _getWidth: function(colIndex){
+ var node = this.grid.layout.cells[colIndex].getHeaderNode();
+ return dojo.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] = [];
+ dojo.forEach(result, function(res){
+ dojo.forEach(res.hiddenCells, function(node){
+ dojo.style(node, "display", "none");
+ });
+ var pbm = dojo.marginBox(res.majorHeaderNode).w - dojo.contentBox(res.majorHeaderNode).w;
+ var tw = res.totalWidth;
+
+ //Tricky for WebKit.
+ if(!dojo.isWebKit){
+ tw -= pbm;
+ }
+
+ dojo.style(res.majorNode, "width", tw + "px");
+ //In case we're dealing with multiple subrows.
+ dojo.attr(res.majorNode, "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(dojo.isFunction(item.row)){
+ this._records.push(item);
+ return item;
+ }
+ }
+ return null;
+ },
+ _isValid: function(item){
+ var cells = this.grid.layout.cells,
+ colCount = cells.length;
+ return (dojo.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);
+ }
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.CellMerge/*name:'cellMerge'*/);
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Cookie.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Cookie.js new file mode 100644 index 0000000..8e0bc88 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Cookie.js @@ -0,0 +1,356 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.Cookie"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Cookie"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Cookie");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojo.cookie");
+dojo.require("dojox.grid._RowSelector");
+dojo.require("dojox.grid.cells._base");
+
+(function(){
+ // 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(!dojo.isArray(structure)){
+ structure = [structure];
+ }
+ dojo.forEach(structure,function(viewDef){
+ if(dojo.isArray(viewDef)){
+ viewDef = {"cells" : viewDef};
+ }
+ var rows = viewDef.rows || viewDef.cells;
+ if(dojo.isArray(rows)){
+ if(!dojo.isArray(rows[0])){
+ rows = [rows];
+ }
+ dojo.forEach(rows, function(row){
+ if(dojo.isArray(row)){
+ dojo.forEach(row, function(cell){
+ cells.push(cell);
+ });
+ }
+ });
+ }
+ });
+ return cells;
+ };
+
+ // Persist column width
+ var _loadColWidth = function(colWidths, grid){
+ if(dojo.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";
+ }
+ }
+ }
+ oldFunc.call(grid, structure);
+ grid._setStructureAttr = oldFunc;
+ };
+ }
+ };
+
+ var _saveColWidth = function(grid){
+ return dojo.map(dojo.filter(grid.layout.cells, function(cell){
+ return !(cell.isRowSelector || cell instanceof dojox.grid.cells.RowIndex);
+ }), function(cell){
+ return dojo[dojo.isWebKit ? "marginBox" : "contentBox"](cell.getHeaderNode()).w;
+ });
+ };
+
+ // Persist column order
+ var _loadColumnOrder = function(colOrder, grid){
+ if(colOrder && dojo.every(colOrder, function(viewInfo){
+ return dojo.isArray(viewInfo) && dojo.every(viewInfo, function(subrowInfo){
+ return dojo.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 && dojo.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 = dojo.clone(structure);
+ if(dojo.isArray(structure) && !dojo.some(structure, isView)){
+ structure = [{ cells: structure }];
+ }else if(isView(structure)){
+ structure = [structure];
+ }
+ var cells = _getCellsFromStructure(structure);
+ dojo.forEach(dojo.isArray(structure) ? structure : [structure], function(viewDef, viewIdx){
+ var cellArray = viewDef;
+ if(dojo.isArray(viewDef)){
+ viewDef.splice(0, viewDef.length);
+ }else{
+ delete viewDef.rows;
+ cellArray = viewDef.cells = [];
+ }
+ dojo.forEach(colOrder[viewIdx], function(subrow){
+ dojo.forEach(subrow, function(cellInfo){
+ var i, cell;
+ for(i = 0; i < cells.length; ++i){
+ cell = cells[i];
+ if(dojo.toJson({'name':cell.name,'field':cell.field}) == dojo.toJson(cellInfo)){
+ break;
+ }
+ }
+ if(i < cells.length){
+ cellArray.push(cell);
+ }
+ });
+ });
+ });
+ }
+ oldFunc.call(grid, structure);
+ };
+ }
+ };
+
+ var _saveColumnOrder = function(grid){
+ var colOrder = dojo.map(dojo.filter(grid.views.views, function(view){
+ return !(view instanceof dojox.grid._RowSelector);
+ }), function(view){
+ return dojo.map(view.structure.cells, function(subrow){
+ return dojo.map(dojo.filter(subrow, function(cell){
+ return !(cell.isRowSelector || cell instanceof dojox.grid.cells.RowIndex);
+ }), function(cell){
+ return {
+ "name": cell.name,
+ "field": cell.field
+ };
+ });
+ });
+ });
+ return colOrder;
+ };
+
+ // Persist sorting order
+ var _loadSortOrder = function(sortOrder, grid){
+ try{
+ if(dojo.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(!dojo.isIE){
+ // Now in non-IE, widgets are no longer destroyed on page unload,
+ // so we have to destroy it manually to trigger saving cookie.
+ dojo.addOnWindowUnload(function(){
+ dojo.forEach(dijit.findWidgets(dojo.body()), function(widget){
+ if(widget instanceof dojox.grid.EnhancedGrid && !widget._destroyed){
+ widget.destroyRecursive();
+ }
+ });
+ });
+ }
+
+ dojo.declare("dojox.grid.enhanced.plugins.Cookie", dojox.grid.enhanced._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 && dojo.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
+ });
+
+ dojo.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 = dojo.hitch(this, "addCookieHandler");
+ g.removeCookie = dojo.hitch(this, "removeCookie");
+ g.setCookieEnabled = dojo.hitch(this, "setCookieEnabled");
+ g.getCookieEnabled = dojo.hitch(this, "getCookieEnabled");
+ },
+ _saveCookie: function(){
+ if(this.getCookieEnabled()){
+ var cookie = {},
+ 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.
+ cookie[chs[i].name] = chs[i].onSave(this.grid);
+ }
+ }
+ cookieProps = dojo.isObject(this.cookieProps) ? this.cookieProps : {};
+ dojo.cookie(cookieKey, dojo.toJson(cookie), cookieProps);
+ }else{
+ this.removeCookie();
+ }
+ },
+ onPreInit: function(){
+ var grid = this.grid,
+ chs = this._cookieHandlers,
+ cookieKey = _cookieKeyBuilder(grid),
+ cookie = dojo.cookie(cookieKey);
+ if(cookie){
+ cookie = dojo.fromJson(cookie);
+ for(var i = 0; i < chs.length; ++i){
+ if(chs[i].name in cookie && chs[i].enabled){
+ //Do the real loading work here.
+ chs[i].onLoad(cookie[chs[i].name], grid);
+ }
+ }
+ }
+ this._cookie = cookie || {};
+ 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);
+ dojo.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(arguments.length == 2){
+ 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(dojo.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;
+ }
+ });
+ dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Cookie/*name:'cookie'*/, {"preInit": true});
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Cookie.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Cookie.xd.js new file mode 100644 index 0000000..d9bf5ed --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Cookie.xd.js @@ -0,0 +1,364 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.Cookie"],
+["require", "dojox.grid.enhanced._Plugin"],
+["require", "dojo.cookie"],
+["require", "dojox.grid._RowSelector"],
+["require", "dojox.grid.cells._base"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.Cookie"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Cookie"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Cookie");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojo.cookie");
+dojo.require("dojox.grid._RowSelector");
+dojo.require("dojox.grid.cells._base");
+
+(function(){
+ // 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(!dojo.isArray(structure)){
+ structure = [structure];
+ }
+ dojo.forEach(structure,function(viewDef){
+ if(dojo.isArray(viewDef)){
+ viewDef = {"cells" : viewDef};
+ }
+ var rows = viewDef.rows || viewDef.cells;
+ if(dojo.isArray(rows)){
+ if(!dojo.isArray(rows[0])){
+ rows = [rows];
+ }
+ dojo.forEach(rows, function(row){
+ if(dojo.isArray(row)){
+ dojo.forEach(row, function(cell){
+ cells.push(cell);
+ });
+ }
+ });
+ }
+ });
+ return cells;
+ };
+
+ // Persist column width
+ var _loadColWidth = function(colWidths, grid){
+ if(dojo.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";
+ }
+ }
+ }
+ oldFunc.call(grid, structure);
+ grid._setStructureAttr = oldFunc;
+ };
+ }
+ };
+
+ var _saveColWidth = function(grid){
+ return dojo.map(dojo.filter(grid.layout.cells, function(cell){
+ return !(cell.isRowSelector || cell instanceof dojox.grid.cells.RowIndex);
+ }), function(cell){
+ return dojo[dojo.isWebKit ? "marginBox" : "contentBox"](cell.getHeaderNode()).w;
+ });
+ };
+
+ // Persist column order
+ var _loadColumnOrder = function(colOrder, grid){
+ if(colOrder && dojo.every(colOrder, function(viewInfo){
+ return dojo.isArray(viewInfo) && dojo.every(viewInfo, function(subrowInfo){
+ return dojo.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 && dojo.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 = dojo.clone(structure);
+ if(dojo.isArray(structure) && !dojo.some(structure, isView)){
+ structure = [{ cells: structure }];
+ }else if(isView(structure)){
+ structure = [structure];
+ }
+ var cells = _getCellsFromStructure(structure);
+ dojo.forEach(dojo.isArray(structure) ? structure : [structure], function(viewDef, viewIdx){
+ var cellArray = viewDef;
+ if(dojo.isArray(viewDef)){
+ viewDef.splice(0, viewDef.length);
+ }else{
+ delete viewDef.rows;
+ cellArray = viewDef.cells = [];
+ }
+ dojo.forEach(colOrder[viewIdx], function(subrow){
+ dojo.forEach(subrow, function(cellInfo){
+ var i, cell;
+ for(i = 0; i < cells.length; ++i){
+ cell = cells[i];
+ if(dojo.toJson({'name':cell.name,'field':cell.field}) == dojo.toJson(cellInfo)){
+ break;
+ }
+ }
+ if(i < cells.length){
+ cellArray.push(cell);
+ }
+ });
+ });
+ });
+ }
+ oldFunc.call(grid, structure);
+ };
+ }
+ };
+
+ var _saveColumnOrder = function(grid){
+ var colOrder = dojo.map(dojo.filter(grid.views.views, function(view){
+ return !(view instanceof dojox.grid._RowSelector);
+ }), function(view){
+ return dojo.map(view.structure.cells, function(subrow){
+ return dojo.map(dojo.filter(subrow, function(cell){
+ return !(cell.isRowSelector || cell instanceof dojox.grid.cells.RowIndex);
+ }), function(cell){
+ return {
+ "name": cell.name,
+ "field": cell.field
+ };
+ });
+ });
+ });
+ return colOrder;
+ };
+
+ // Persist sorting order
+ var _loadSortOrder = function(sortOrder, grid){
+ try{
+ if(dojo.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(!dojo.isIE){
+ // Now in non-IE, widgets are no longer destroyed on page unload,
+ // so we have to destroy it manually to trigger saving cookie.
+ dojo.addOnWindowUnload(function(){
+ dojo.forEach(dijit.findWidgets(dojo.body()), function(widget){
+ if(widget instanceof dojox.grid.EnhancedGrid && !widget._destroyed){
+ widget.destroyRecursive();
+ }
+ });
+ });
+ }
+
+ dojo.declare("dojox.grid.enhanced.plugins.Cookie", dojox.grid.enhanced._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 && dojo.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
+ });
+
+ dojo.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 = dojo.hitch(this, "addCookieHandler");
+ g.removeCookie = dojo.hitch(this, "removeCookie");
+ g.setCookieEnabled = dojo.hitch(this, "setCookieEnabled");
+ g.getCookieEnabled = dojo.hitch(this, "getCookieEnabled");
+ },
+ _saveCookie: function(){
+ if(this.getCookieEnabled()){
+ var cookie = {},
+ 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.
+ cookie[chs[i].name] = chs[i].onSave(this.grid);
+ }
+ }
+ cookieProps = dojo.isObject(this.cookieProps) ? this.cookieProps : {};
+ dojo.cookie(cookieKey, dojo.toJson(cookie), cookieProps);
+ }else{
+ this.removeCookie();
+ }
+ },
+ onPreInit: function(){
+ var grid = this.grid,
+ chs = this._cookieHandlers,
+ cookieKey = _cookieKeyBuilder(grid),
+ cookie = dojo.cookie(cookieKey);
+ if(cookie){
+ cookie = dojo.fromJson(cookie);
+ for(var i = 0; i < chs.length; ++i){
+ if(chs[i].name in cookie && chs[i].enabled){
+ //Do the real loading work here.
+ chs[i].onLoad(cookie[chs[i].name], grid);
+ }
+ }
+ }
+ this._cookie = cookie || {};
+ 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);
+ dojo.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(arguments.length == 2){
+ 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(dojo.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;
+ }
+ });
+ dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Cookie/*name:'cookie'*/, {"preInit": true});
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Dialog.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Dialog.js new file mode 100644 index 0000000..457a8c0 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Dialog.js @@ -0,0 +1,45 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.Dialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Dialog"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Dialog");
+
+dojo.require("dijit.Dialog");
+dojo.require("dojo.window");
+
+dojo.declare("dojox.grid.enhanced.plugins.Dialog", dijit.Dialog, {
+ refNode: null,
+ _position: function(){
+ if(this.refNode && !this._relativePosition){
+ var refPos = dojo.position(dojo.byId(this.refNode)),
+ thisPos = dojo.position(this.domNode),
+ viewPort = dojo.window.getBox();
+ 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-1.6/dojox/grid/enhanced/plugins/Dialog.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Dialog.xd.js new file mode 100644 index 0000000..9cd3b0e --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Dialog.xd.js @@ -0,0 +1,51 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.Dialog"],
+["require", "dijit.Dialog"],
+["require", "dojo.window"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.Dialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Dialog"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Dialog");
+
+dojo.require("dijit.Dialog");
+dojo.require("dojo.window");
+
+dojo.declare("dojox.grid.enhanced.plugins.Dialog", dijit.Dialog, {
+ refNode: null,
+ _position: function(){
+ if(this.refNode && !this._relativePosition){
+ var refPos = dojo.position(dojo.byId(this.refNode)),
+ thisPos = dojo.position(this.domNode),
+ viewPort = dojo.window.getBox();
+ 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-1.6/dojox/grid/enhanced/plugins/DnD.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/DnD.js new file mode 100644 index 0000000..8c5d8f1 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/DnD.js @@ -0,0 +1,1085 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.DnD"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.DnD"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.DnD");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid.enhanced.plugins.Selector");
+dojo.require("dojox.grid.enhanced.plugins.Rearrange");
+dojo.require("dojo.dnd.move");
+dojo.require("dojo.dnd.Source");
+
+(function(){
+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;
+ };
+dojo.declare("dojox.grid.enhanced.plugins.DnD", dojox.grid.enhanced._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 = dojo.clone(this._config);
+ args = dojo.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 dojox.grid.enhanced.plugins.GridDnDElement(this);
+ this._source = new dojox.grid.enhanced.plugins.GridDnDSource(this._elem.node, {
+ "grid": grid,
+ "dndElem": this._elem,
+ "dnd": this
+ });
+ this._container = dojo.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 = dojo.hitch(this, "setupConfig");
+ this.grid.dndCopyOnly = dojo.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 && dojo.isObject(config)){
+ var firstLevel = ["row", "col", "cell"],
+ secondLevel = ["within", "in", "out"],
+ cfg = this._config;
+ dojo.forEach(firstLevel, function(type){
+ if(type in config){
+ var t = config[type];
+ if(t && dojo.isObject(t)){
+ dojo.forEach(secondLevel, function(mode){
+ if(mode in t){
+ cfg[type][mode] = !!t[mode];
+ }
+ });
+ }else{
+ dojo.forEach(secondLevel, function(mode){
+ cfg[type][mode] = !!t;
+ });
+ }
+ }
+ });
+ dojo.forEach(secondLevel, function(mode){
+ if(mode in config){
+ var m = config[mode];
+ if(m && dojo.isObject(m)){
+ dojo.forEach(firstLevel, function(type){
+ if(type in m){
+ cfg[type][mode] = !!m[type];
+ }
+ });
+ }else{
+ dojo.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 = dojo.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 = dojo.style(dojo.body(), "cursor");
+ dojo.style(dojo.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);
+ }
+ dojo.style(dojo.body(), "cursor", this._oldCursor || "");
+ delete this._isMouseDown;
+ },
+ _initEvents: function(){
+ var g = this.grid, s = this.selector;
+ this.connect(dojo.doc, "onmousemove", "_onMouseMove");
+ this.connect(dojo.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(dojo.doc, "onkeydown", function(evt){
+ if(evt.keyCode == dojo.keys.ESCAPE){
+ this._endDnd(false);
+ }else if(evt.keyCode == dojo.keys.CTRL){
+ s.selectEnabled(true);
+ this._isCopy = true;
+ }
+ });
+ this.connect(dojo.doc, "onkeyup", function(evt){
+ if(evt.keyCode == dojo.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
+ }
+ };
+
+ dojo.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(dojo.some(selected[type], function(item){
+ return item.row == rowIndex && item.col == colIndex;
+ })){
+ if(getCount(range) == selected[type].length && dojo.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 = dojo.position(this.grid.views.views[0].domNode);
+ dojo.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 = dojo.style(dojo.body(), "cursor");
+ dojo.style(dojo.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();
+ }
+ dojo.style(dojo.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 dojox.grid.enhanced.plugins.GridDnDAvatar(m);
+ delete m._dndPlugin;
+ return avatar;
+ };
+ m.startDrag(this._source, this._elem.getDnDNodes(), evt.ctrlKey);
+ m.makeAvatar = oldMakeAvatar;
+ m.onMouseMove(evt);
+ },
+ _destroySource: function(){
+ dojo.publish("/dnd/cancel");
+ this._elem.destroyDnDNodes();
+ },
+ _createMoveable: function(evt){
+ if(!this._markTagetAnchorHandler){
+ this._markTagetAnchorHandler = this.connect(dojo.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 = dojo._isBodyLtr(),
+ headers = this._getVisibleHeaders();
+ for(i = 0; i < headers.length; ++i){
+ headPos = dojo.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(dojo.indexOf(ranges[i], target) >= 0){
+ target = ranges[i][0];
+ headPos = dojo.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,
+ nodePos = dojo.position(cell.getNode(rowIndex));
+ while(nodePos.y + nodePos.h < evt.clientY){
+ if(++rowIndex >= g.rowCount){
+ break;
+ }
+ nodePos = dojo.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(dojo.indexOf(ranges[i], rowIndex) >= 0){
+ rowIndex = ranges[i][0];
+ nodePos = dojo.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 = dojo._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 = dojo.create("div", {
+ "class": "dojoxGridCellBorderLeftTopDIV"
+ }, targetAnchor);
+ rightBottomDiv = dojo.create("div", {
+ "class": "dojoxGridCellBorderRightBottomDIV"
+ }, targetAnchor);
+ }else{
+ leftTopDiv = dojo.query(".dojoxGridCellBorderLeftTopDIV", targetAnchor)[0];
+ rightBottomDiv = dojo.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 = dojo.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 = dojo.position(minCol.node);
+ maxPos = dojo.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 = dojo.position(cell.getNode(rowIndex));
+ while(nodePos.y + nodePos.h < evt.clientY){
+ if(++rowIndex < g.rowCount){
+ nodePos = dojo.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 = dojo.position(cell.getNode(minRow));
+ maxPos = dojo.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 = (dojo.marginBox(leftTopDiv).w - dojo.contentBox(leftTopDiv).w) / 2;
+ var leftTopCellPos = dojo.position(cells[minCol].getNode(minRow));
+ dojo.style(leftTopDiv, {
+ "width": (leftTopCellPos.w - anchorBorderSize) + "px",
+ "height": (leftTopCellPos.h - anchorBorderSize) + "px"
+ });
+ var rightBottomCellPos = dojo.position(cells[maxCol].getNode(maxRow));
+ dojo.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 = dojo.position(this._container);
+ if(!targetAnchor){
+ targetAnchor = this._targetAnchor[t] = dojo.create("div", {
+ "class": (t == "cell") ? "dojoxGridCellBorderDIV" : "dojoxGridBorderDIV"
+ });
+ dojo.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"){
+ dojo.style(targetAnchor, {
+ "height": height + "px",
+ "width": width + "px",
+ "left": left + "px",
+ "top": top + "px"
+ });
+ dojo.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){
+ dojo.style(this._targetAnchor[this._dndRegion.type], "display", "none");
+ }
+ }
+ },
+ _getVisibleHeaders: function(){
+ return dojo.map(dojo.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);
+ }else{
+ this.rearranger[t == "col" ? "moveColumns" : "moveRows"](_joinToArray(ranges), 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 = dojo.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 = dojo.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 &&
+ dojo.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 dojo.every(rows, function(rowIndex){
+ return !!cache[rowIndex];
+ });
+ }
+ return false;
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.GridDnDElement", null, {
+ constructor: function(dndPlugin){
+ this.plugin = dndPlugin;
+ this.node = dojo.create("div");
+ this._items = {};
+ },
+ destroy: function(){
+ this.plugin = null;
+ dojo.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";
+ dojo.forEach(dndRegion.selected, function(range, i){
+ var id = itemNodeIdBase + i;
+ this._items[id] = {
+ "type": acceptType,
+ "data": range,
+ "dndPlugin": this.plugin
+ };
+ this.node.appendChild(dojo.create("div", {
+ "id": id
+ }));
+ }, this);
+ },
+ getDnDNodes: function(){
+ return dojo.map(this.node.childNodes, function(node){
+ return node;
+ });
+ },
+ destroyDnDNodes: function(){
+ dojo.empty(this.node);
+ this._items = {};
+ },
+ getItem: function(nodeId){
+ return this._items[nodeId];
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.GridDnDSource",dojo.dnd.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 = [];
+ dojo.forEach(nodes, function(node){
+ var item = source.getItem(node.id);
+ if(item.data && dojo.indexOf(item.type, "grid/rows") >= 0){
+ var rowData = item.data;
+ if(typeof item.data == "string"){
+ rowData = dojo.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);
+ }
+ }
+});
+
+dojo.declare("dojox.grid.enhanced.plugins.GridDnDAvatar", dojo.dnd.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 = dojo.hasClass(dojo.body(), "dijit_a11y");
+ var a = dojo.create("table", {
+ "border": "0",
+ "cellspacing": "0",
+ "class": "dojoxGridDndAvatar",
+ "style": {
+ position: "absolute",
+ zIndex: "1999",
+ margin: "0px"
+ }
+ }),
+ source = this.manager.source,
+ b = dojo.create("tbody", null, a),
+ tr = dojo.create("tr", null, b),
+ td = dojo.create("td", {
+ "class": "dojoxGridDnDIcon"
+ }, tr);
+ if(this.isA11y){
+ dojo.create("span", {
+ "id" : "a11yIcon",
+ "innerHTML" : this.manager.copy ? '+' : "<"
+ }, td);
+ }
+ td = dojo.create("td", {
+ "class" : "dojoxGridDnDItemIcon " + this._getGridDnDIconClass()
+ }, tr);
+ td = dojo.create("td", null, tr);
+ dojo.create("span", {
+ "class": "dojoxGridDnDItemCount",
+ "innerHTML": source.generateText ? this._generateText() : ""
+ }, td);
+ // we have to set the opacity on IE only after the node is live
+ dojo.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 + ")";
+ }
+});
+
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.DnD/*name:'dnd'*/, {
+ "dependency": ["selector", "rearrange"]
+});
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/DnD.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/DnD.xd.js new file mode 100644 index 0000000..0bbb5a7 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/DnD.xd.js @@ -0,0 +1,1094 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.DnD"],
+["require", "dojox.grid.enhanced._Plugin"],
+["require", "dojox.grid.enhanced.plugins.Selector"],
+["require", "dojox.grid.enhanced.plugins.Rearrange"],
+["require", "dojo.dnd.move"],
+["require", "dojo.dnd.Source"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.DnD"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.DnD"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.DnD");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid.enhanced.plugins.Selector");
+dojo.require("dojox.grid.enhanced.plugins.Rearrange");
+dojo.require("dojo.dnd.move");
+dojo.require("dojo.dnd.Source");
+
+(function(){
+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;
+ };
+dojo.declare("dojox.grid.enhanced.plugins.DnD", dojox.grid.enhanced._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 = dojo.clone(this._config);
+ args = dojo.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 dojox.grid.enhanced.plugins.GridDnDElement(this);
+ this._source = new dojox.grid.enhanced.plugins.GridDnDSource(this._elem.node, {
+ "grid": grid,
+ "dndElem": this._elem,
+ "dnd": this
+ });
+ this._container = dojo.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 = dojo.hitch(this, "setupConfig");
+ this.grid.dndCopyOnly = dojo.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 && dojo.isObject(config)){
+ var firstLevel = ["row", "col", "cell"],
+ secondLevel = ["within", "in", "out"],
+ cfg = this._config;
+ dojo.forEach(firstLevel, function(type){
+ if(type in config){
+ var t = config[type];
+ if(t && dojo.isObject(t)){
+ dojo.forEach(secondLevel, function(mode){
+ if(mode in t){
+ cfg[type][mode] = !!t[mode];
+ }
+ });
+ }else{
+ dojo.forEach(secondLevel, function(mode){
+ cfg[type][mode] = !!t;
+ });
+ }
+ }
+ });
+ dojo.forEach(secondLevel, function(mode){
+ if(mode in config){
+ var m = config[mode];
+ if(m && dojo.isObject(m)){
+ dojo.forEach(firstLevel, function(type){
+ if(type in m){
+ cfg[type][mode] = !!m[type];
+ }
+ });
+ }else{
+ dojo.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 = dojo.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 = dojo.style(dojo.body(), "cursor");
+ dojo.style(dojo.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);
+ }
+ dojo.style(dojo.body(), "cursor", this._oldCursor || "");
+ delete this._isMouseDown;
+ },
+ _initEvents: function(){
+ var g = this.grid, s = this.selector;
+ this.connect(dojo.doc, "onmousemove", "_onMouseMove");
+ this.connect(dojo.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(dojo.doc, "onkeydown", function(evt){
+ if(evt.keyCode == dojo.keys.ESCAPE){
+ this._endDnd(false);
+ }else if(evt.keyCode == dojo.keys.CTRL){
+ s.selectEnabled(true);
+ this._isCopy = true;
+ }
+ });
+ this.connect(dojo.doc, "onkeyup", function(evt){
+ if(evt.keyCode == dojo.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
+ }
+ };
+
+ dojo.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(dojo.some(selected[type], function(item){
+ return item.row == rowIndex && item.col == colIndex;
+ })){
+ if(getCount(range) == selected[type].length && dojo.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 = dojo.position(this.grid.views.views[0].domNode);
+ dojo.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 = dojo.style(dojo.body(), "cursor");
+ dojo.style(dojo.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();
+ }
+ dojo.style(dojo.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 dojox.grid.enhanced.plugins.GridDnDAvatar(m);
+ delete m._dndPlugin;
+ return avatar;
+ };
+ m.startDrag(this._source, this._elem.getDnDNodes(), evt.ctrlKey);
+ m.makeAvatar = oldMakeAvatar;
+ m.onMouseMove(evt);
+ },
+ _destroySource: function(){
+ dojo.publish("/dnd/cancel");
+ this._elem.destroyDnDNodes();
+ },
+ _createMoveable: function(evt){
+ if(!this._markTagetAnchorHandler){
+ this._markTagetAnchorHandler = this.connect(dojo.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 = dojo._isBodyLtr(),
+ headers = this._getVisibleHeaders();
+ for(i = 0; i < headers.length; ++i){
+ headPos = dojo.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(dojo.indexOf(ranges[i], target) >= 0){
+ target = ranges[i][0];
+ headPos = dojo.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,
+ nodePos = dojo.position(cell.getNode(rowIndex));
+ while(nodePos.y + nodePos.h < evt.clientY){
+ if(++rowIndex >= g.rowCount){
+ break;
+ }
+ nodePos = dojo.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(dojo.indexOf(ranges[i], rowIndex) >= 0){
+ rowIndex = ranges[i][0];
+ nodePos = dojo.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 = dojo._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 = dojo.create("div", {
+ "class": "dojoxGridCellBorderLeftTopDIV"
+ }, targetAnchor);
+ rightBottomDiv = dojo.create("div", {
+ "class": "dojoxGridCellBorderRightBottomDIV"
+ }, targetAnchor);
+ }else{
+ leftTopDiv = dojo.query(".dojoxGridCellBorderLeftTopDIV", targetAnchor)[0];
+ rightBottomDiv = dojo.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 = dojo.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 = dojo.position(minCol.node);
+ maxPos = dojo.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 = dojo.position(cell.getNode(rowIndex));
+ while(nodePos.y + nodePos.h < evt.clientY){
+ if(++rowIndex < g.rowCount){
+ nodePos = dojo.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 = dojo.position(cell.getNode(minRow));
+ maxPos = dojo.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 = (dojo.marginBox(leftTopDiv).w - dojo.contentBox(leftTopDiv).w) / 2;
+ var leftTopCellPos = dojo.position(cells[minCol].getNode(minRow));
+ dojo.style(leftTopDiv, {
+ "width": (leftTopCellPos.w - anchorBorderSize) + "px",
+ "height": (leftTopCellPos.h - anchorBorderSize) + "px"
+ });
+ var rightBottomCellPos = dojo.position(cells[maxCol].getNode(maxRow));
+ dojo.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 = dojo.position(this._container);
+ if(!targetAnchor){
+ targetAnchor = this._targetAnchor[t] = dojo.create("div", {
+ "class": (t == "cell") ? "dojoxGridCellBorderDIV" : "dojoxGridBorderDIV"
+ });
+ dojo.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"){
+ dojo.style(targetAnchor, {
+ "height": height + "px",
+ "width": width + "px",
+ "left": left + "px",
+ "top": top + "px"
+ });
+ dojo.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){
+ dojo.style(this._targetAnchor[this._dndRegion.type], "display", "none");
+ }
+ }
+ },
+ _getVisibleHeaders: function(){
+ return dojo.map(dojo.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);
+ }else{
+ this.rearranger[t == "col" ? "moveColumns" : "moveRows"](_joinToArray(ranges), 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 = dojo.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 = dojo.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 &&
+ dojo.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 dojo.every(rows, function(rowIndex){
+ return !!cache[rowIndex];
+ });
+ }
+ return false;
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.GridDnDElement", null, {
+ constructor: function(dndPlugin){
+ this.plugin = dndPlugin;
+ this.node = dojo.create("div");
+ this._items = {};
+ },
+ destroy: function(){
+ this.plugin = null;
+ dojo.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";
+ dojo.forEach(dndRegion.selected, function(range, i){
+ var id = itemNodeIdBase + i;
+ this._items[id] = {
+ "type": acceptType,
+ "data": range,
+ "dndPlugin": this.plugin
+ };
+ this.node.appendChild(dojo.create("div", {
+ "id": id
+ }));
+ }, this);
+ },
+ getDnDNodes: function(){
+ return dojo.map(this.node.childNodes, function(node){
+ return node;
+ });
+ },
+ destroyDnDNodes: function(){
+ dojo.empty(this.node);
+ this._items = {};
+ },
+ getItem: function(nodeId){
+ return this._items[nodeId];
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.GridDnDSource",dojo.dnd.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 = [];
+ dojo.forEach(nodes, function(node){
+ var item = source.getItem(node.id);
+ if(item.data && dojo.indexOf(item.type, "grid/rows") >= 0){
+ var rowData = item.data;
+ if(typeof item.data == "string"){
+ rowData = dojo.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);
+ }
+ }
+});
+
+dojo.declare("dojox.grid.enhanced.plugins.GridDnDAvatar", dojo.dnd.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 = dojo.hasClass(dojo.body(), "dijit_a11y");
+ var a = dojo.create("table", {
+ "border": "0",
+ "cellspacing": "0",
+ "class": "dojoxGridDndAvatar",
+ "style": {
+ position: "absolute",
+ zIndex: "1999",
+ margin: "0px"
+ }
+ }),
+ source = this.manager.source,
+ b = dojo.create("tbody", null, a),
+ tr = dojo.create("tr", null, b),
+ td = dojo.create("td", {
+ "class": "dojoxGridDnDIcon"
+ }, tr);
+ if(this.isA11y){
+ dojo.create("span", {
+ "id" : "a11yIcon",
+ "innerHTML" : this.manager.copy ? '+' : "<"
+ }, td);
+ }
+ td = dojo.create("td", {
+ "class" : "dojoxGridDnDItemIcon " + this._getGridDnDIconClass()
+ }, tr);
+ td = dojo.create("td", null, tr);
+ dojo.create("span", {
+ "class": "dojoxGridDnDItemCount",
+ "innerHTML": source.generateText ? this._generateText() : ""
+ }, td);
+ // we have to set the opacity on IE only after the node is live
+ dojo.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 + ")";
+ }
+});
+
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.DnD/*name:'dnd'*/, {
+ "dependency": ["selector", "rearrange"]
+});
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Exporter.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Exporter.js new file mode 100644 index 0000000..5b2c164 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Exporter.js @@ -0,0 +1,242 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.Exporter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Exporter"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Exporter");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid._RowSelector");
+
+dojo.declare("dojox.grid.enhanced.plugins.Exporter", dojox.grid.enhanced._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 && dojo.isObject(args)) && args.exportFormatter;
+ this._mixinGrid();
+ },
+ _mixinGrid: function(){
+ var g = this.grid;
+ g.exportTo = dojo.hitch(this, this.exportTo);
+ g.exportGrid = dojo.hitch(this, this.exportGrid);
+ g.exportSelected = dojo.hitch(this, this.exportSelected);
+ g.setExportFormatter = dojo.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(dojo.isFunction(args)){
+ onExported = args;
+ args = {};
+ }
+ if(!dojo.isString(type) || !dojo.isFunction(onExported)){
+ return;
+ }
+ args = args || {};
+ var g = this.grid, _this = this,
+ writer = this._getExportWriter(type, args.writerArgs),
+ fetchArgs = (args.fetchArgs && dojo.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(!dojo.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;
+ dojo.forEach(arg_obj._views, function(view, vIdx){
+ arg_obj.view = view;
+ arg_obj.viewIdx = vIdx;
+ if(writer.beforeView(arg_obj)){
+ dojo.forEach(view.structure.cells, function(subrow, srIdx){
+ arg_obj.subrow = subrow;
+ arg_obj.subrowIdx = srIdx;
+ if(writer.beforeSubrow(arg_obj)){
+ dojo.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 = dojo.filter(grid.views.views, function(view){
+ return !(view instanceof dojox.grid._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)){
+ dojo.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 dojox.grid.cells.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 = dojox.grid.enhanced.plugins.Exporter;
+ if(expCls.writerNames){
+ writerName = expCls.writerNames[fileType.toLowerCase()];
+ cls = dojo.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.');
+ }
+});
+dojox.grid.enhanced.plugins.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
+ var expCls = dojox.grid.enhanced.plugins.Exporter;
+ expCls.writerNames = expCls.writerNames || {};
+ expCls.writerNames[fileType] = writerClsName;
+};
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Exporter/*name:'exporter'*/);
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Exporter.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Exporter.xd.js new file mode 100644 index 0000000..dd254e0 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Exporter.xd.js @@ -0,0 +1,248 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.Exporter"],
+["require", "dojox.grid.enhanced._Plugin"],
+["require", "dojox.grid._RowSelector"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.Exporter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Exporter"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Exporter");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid._RowSelector");
+
+dojo.declare("dojox.grid.enhanced.plugins.Exporter", dojox.grid.enhanced._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 && dojo.isObject(args)) && args.exportFormatter;
+ this._mixinGrid();
+ },
+ _mixinGrid: function(){
+ var g = this.grid;
+ g.exportTo = dojo.hitch(this, this.exportTo);
+ g.exportGrid = dojo.hitch(this, this.exportGrid);
+ g.exportSelected = dojo.hitch(this, this.exportSelected);
+ g.setExportFormatter = dojo.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(dojo.isFunction(args)){
+ onExported = args;
+ args = {};
+ }
+ if(!dojo.isString(type) || !dojo.isFunction(onExported)){
+ return;
+ }
+ args = args || {};
+ var g = this.grid, _this = this,
+ writer = this._getExportWriter(type, args.writerArgs),
+ fetchArgs = (args.fetchArgs && dojo.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(!dojo.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;
+ dojo.forEach(arg_obj._views, function(view, vIdx){
+ arg_obj.view = view;
+ arg_obj.viewIdx = vIdx;
+ if(writer.beforeView(arg_obj)){
+ dojo.forEach(view.structure.cells, function(subrow, srIdx){
+ arg_obj.subrow = subrow;
+ arg_obj.subrowIdx = srIdx;
+ if(writer.beforeSubrow(arg_obj)){
+ dojo.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 = dojo.filter(grid.views.views, function(view){
+ return !(view instanceof dojox.grid._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)){
+ dojo.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 dojox.grid.cells.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 = dojox.grid.enhanced.plugins.Exporter;
+ if(expCls.writerNames){
+ writerName = expCls.writerNames[fileType.toLowerCase()];
+ cls = dojo.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.');
+ }
+});
+dojox.grid.enhanced.plugins.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
+ var expCls = dojox.grid.enhanced.plugins.Exporter;
+ expCls.writerNames = expCls.writerNames || {};
+ expCls.writerNames[fileType] = writerClsName;
+};
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Exporter/*name:'exporter'*/);
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Filter.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Filter.js new file mode 100644 index 0000000..ea87100 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Filter.js @@ -0,0 +1,171 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.Filter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Filter"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Filter");
+
+dojo.requireLocalization("dojox.grid.enhanced", "Filter", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ru,sl,sv,th,tr,zh,zh-tw");
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid.enhanced.plugins.Dialog");
+dojo.require("dojox.grid.enhanced.plugins.filter.FilterLayer");
+dojo.require("dojox.grid.enhanced.plugins.filter.FilterBar");
+dojo.require("dojox.grid.enhanced.plugins.filter.FilterDefDialog");
+dojo.require("dojox.grid.enhanced.plugins.filter.FilterStatusTip");
+dojo.require("dojox.grid.enhanced.plugins.filter.ClearFilterConfirm");
+
+(function(){
+ var ns = dojox.grid.enhanced.plugins,
+ fns = ns.filter;
+
+ dojo.declare("dojox.grid.enhanced.plugins.Filter", dojox.grid.enhanced._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.
+ //
+ // 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 = dojo.i18n.getLocalization("dojox.grid.enhanced", "Filter");
+
+ args = this.args = dojo.isObject(args) ? args : {};
+ if(typeof args.ruleCount != 'number' || args.ruleCount < 0){
+ args.ruleCount = 3;
+ }
+
+ //Install filter layer
+ this._wrapStore();
+
+ //Install UI components
+ var obj = { "plugin": this };
+ this.clearFilterDialog = new dojox.grid.enhanced.plugins.Dialog({
+ refNode: this.grid.domNode,
+ title: this.nls["clearFilterDialogTitle"],
+ content: new fns.ClearFilterConfirm(obj)
+ });
+ this.filterDefDialog = new fns.FilterDefDialog(obj);
+ this.filterBar = new fns.FilterBar(obj);
+ this.filterStatusTip = new fns.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 fns.ServerSideFilterLayer(args) :
+ new fns.ClientSideFilterLayer({
+ cacheSize: args.filterCacheSize,
+ fetchAll: args.fetchAllOnFirstFilter,
+ getter: this._clientFilterGetter
+ });
+ ns.wrap(g, "_storeLayerFetch", filterLayer);
+
+ this.connect(g, "_onDelete", dojo.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);
+ }
+ });
+})();
+
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Filter/*name:'filter'*/);
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Filter.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Filter.xd.js new file mode 100644 index 0000000..59c80a5 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Filter.xd.js @@ -0,0 +1,183 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.Filter"],
+["requireLocalization", "dojox.grid.enhanced", "Filter", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ru,sl,sv,th,tr,zh,zh-tw", "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ru,sl,sv,th,tr,zh,zh-tw"],
+["require", "dojox.grid.enhanced._Plugin"],
+["require", "dojox.grid.enhanced.plugins.Dialog"],
+["require", "dojox.grid.enhanced.plugins.filter.FilterLayer"],
+["require", "dojox.grid.enhanced.plugins.filter.FilterBar"],
+["require", "dojox.grid.enhanced.plugins.filter.FilterDefDialog"],
+["require", "dojox.grid.enhanced.plugins.filter.FilterStatusTip"],
+["require", "dojox.grid.enhanced.plugins.filter.ClearFilterConfirm"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.Filter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Filter"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Filter");
+
+;
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid.enhanced.plugins.Dialog");
+dojo.require("dojox.grid.enhanced.plugins.filter.FilterLayer");
+dojo.require("dojox.grid.enhanced.plugins.filter.FilterBar");
+dojo.require("dojox.grid.enhanced.plugins.filter.FilterDefDialog");
+dojo.require("dojox.grid.enhanced.plugins.filter.FilterStatusTip");
+dojo.require("dojox.grid.enhanced.plugins.filter.ClearFilterConfirm");
+
+(function(){
+ var ns = dojox.grid.enhanced.plugins,
+ fns = ns.filter;
+
+ dojo.declare("dojox.grid.enhanced.plugins.Filter", dojox.grid.enhanced._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.
+ //
+ // 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 = dojo.i18n.getLocalization("dojox.grid.enhanced", "Filter");
+
+ args = this.args = dojo.isObject(args) ? args : {};
+ if(typeof args.ruleCount != 'number' || args.ruleCount < 0){
+ args.ruleCount = 3;
+ }
+
+ //Install filter layer
+ this._wrapStore();
+
+ //Install UI components
+ var obj = { "plugin": this };
+ this.clearFilterDialog = new dojox.grid.enhanced.plugins.Dialog({
+ refNode: this.grid.domNode,
+ title: this.nls["clearFilterDialogTitle"],
+ content: new fns.ClearFilterConfirm(obj)
+ });
+ this.filterDefDialog = new fns.FilterDefDialog(obj);
+ this.filterBar = new fns.FilterBar(obj);
+ this.filterStatusTip = new fns.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 fns.ServerSideFilterLayer(args) :
+ new fns.ClientSideFilterLayer({
+ cacheSize: args.filterCacheSize,
+ fetchAll: args.fetchAllOnFirstFilter,
+ getter: this._clientFilterGetter
+ });
+ ns.wrap(g, "_storeLayerFetch", filterLayer);
+
+ this.connect(g, "_onDelete", dojo.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);
+ }
+ });
+})();
+
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Filter/*name:'filter'*/);
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/GridSource.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/GridSource.js new file mode 100644 index 0000000..0a02402 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/GridSource.js @@ -0,0 +1,159 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.GridSource"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.GridSource"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.GridSource");
+
+dojo.require("dojo.dnd.Source");
+dojo.require("dojox.grid.enhanced.plugins.DnD");
+
+(function(){
+var _joinToArray = function(arrays){
+ var a = arrays[0];
+ for(var i = 1; i < arrays.length; ++i){
+ a = a.concat(arrays[i]);
+ }
+ return a;
+};
+dojo.declare("dojox.grid.enhanced.plugins.GridSource", dojo.dnd.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){
+ return new dojox.grid.enhanced.plugins.GridSource(node, params);
+ },
+ checkAcceptance: function(source, nodes){
+ if(source instanceof dojox.grid.enhanced.plugins.GridDnDSource){
+ if(nodes[0]){
+ var item = source.getItem(nodes[0].id);
+ if(item && (dojo.indexOf(item.type, "grid/rows") >= 0 || dojo.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 dojox.grid.enhanced.plugins.GridDnDSource){
+ var ranges = dojo.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-1.6/dojox/grid/enhanced/plugins/GridSource.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/GridSource.xd.js new file mode 100644 index 0000000..4398814 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/GridSource.xd.js @@ -0,0 +1,165 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.GridSource"],
+["require", "dojo.dnd.Source"],
+["require", "dojox.grid.enhanced.plugins.DnD"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.GridSource"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.GridSource"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.GridSource");
+
+dojo.require("dojo.dnd.Source");
+dojo.require("dojox.grid.enhanced.plugins.DnD");
+
+(function(){
+var _joinToArray = function(arrays){
+ var a = arrays[0];
+ for(var i = 1; i < arrays.length; ++i){
+ a = a.concat(arrays[i]);
+ }
+ return a;
+};
+dojo.declare("dojox.grid.enhanced.plugins.GridSource", dojo.dnd.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){
+ return new dojox.grid.enhanced.plugins.GridSource(node, params);
+ },
+ checkAcceptance: function(source, nodes){
+ if(source instanceof dojox.grid.enhanced.plugins.GridDnDSource){
+ if(nodes[0]){
+ var item = source.getItem(nodes[0].id);
+ if(item && (dojo.indexOf(item.type, "grid/rows") >= 0 || dojo.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 dojox.grid.enhanced.plugins.GridDnDSource){
+ var ranges = dojo.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-1.6/dojox/grid/enhanced/plugins/IndirectSelection.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/IndirectSelection.js new file mode 100644 index 0000000..f27ec28 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/IndirectSelection.js @@ -0,0 +1,616 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.IndirectSelection"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.IndirectSelection"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.IndirectSelection");
+
+dojo.require('dojo.string');
+dojo.require("dojox.grid.cells.dijit");
+dojo.require("dojox.grid.enhanced._Plugin");
+
+dojo.declare("dojox.grid.enhanced.plugins.IndirectSelection", dojox.grid.enhanced._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', dojo.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: dojox.grid.cells.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();
+ }
+
+ dojo.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' ? dojox.grid.cells.SingleRowSelector : dojox.grid.cells.MultipleRowSelector;
+ selectDef = dojo.mixin(defaultCellDef, option, {type: cellType, editable: false, notselectable: true, filterable: false, navigatable: true, nosort: true});
+ dojo.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
+ dojo.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);
+ }
+});
+
+dojo.declare("dojox.grid.cells.RowSelector", dojox.grid.cells._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: '√',
+
+ //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 = dojo.hasClass(dojo.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(dojo.connect(this.grid, 'dokeyup', this, '_dokeyup'));
+ this._connects.push(dojo.connect(this.grid.selection, 'onSelected', this, '_onSelected'));
+ this._connects.push(dojo.connect(this.grid.selection, 'onDeselected', this, '_onDeselected'));
+ this._connects.push(dojo.connect(this.grid.scroller, 'invalidatePageNode', this, '_pageDestroyed'));
+ this._connects.push(dojo.connect(this.grid, 'onCellClick', this, '_onClick'));
+ this._connects.push(dojo.connect(this.grid, 'updateRow', this, '_onUpdateRow'));
+ },
+ formatter: function(data, rowIndex){
+ // summary:
+ // Overwritten, see dojox.grid.cells._Widget
+ 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 = '" + dojo.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 == dojo.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){
+ dojo.toggleClass(selector, this.checkedClass, value);
+ if(this.disabledMap[index]){
+ dojo.toggleClass(selector, this.checkedDisabledClass, value);
+ }
+ dijit.setWaiState(selector, 'pressed', value);
+ if(this.inA11YMode){
+ dojo.attr(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){
+ dojo.toggleClass(selector, this.disabledClass, disabled);
+ if(this.getValue(index)){
+ dojo.toggleClass(selector, this.checkedDisabledClass, disabled);
+ }
+ dijit.setWaiState(selector, '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 = dojo.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;}
+ dojo.destroy(this.map[i]);
+ delete this.map[i];
+ }
+ //console.log("Page ",pageIndex, " destroyed, Map=",this.map);
+ },
+ destroy: function(){
+ for(var i in this.map){
+ dojo.destroy(this.map[i]);
+ delete this.map[i];
+ }
+ for(i in this.disabledMap){ delete this.disabledMap[i]; }
+ dojo.forEach(this._connects, dojo.disconnect);
+ dojo.forEach(this._subscribes, dojo.unsubscribe);
+ delete this._connects;
+ delete this._subscribes;
+ //console.log('Single(Multiple)RowSelector.destroy() executed!');
+ }
+});
+
+dojo.declare("dojox.grid.cells.SingleRowSelector", dojox.grid.cells.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]);
+ }
+});
+
+dojo.declare("dojox.grid.cells.MultipleRowSelector", dojox.grid.cells.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: '□',
+
+ constructor: function(){
+ this._connects.push(dojo.connect(dojo.doc, 'onmouseup', this, '_domouseup'));
+ this._connects.push(dojo.connect(this.grid, 'onRowMouseOver', this, '_onRowMouseOver'));
+ this._connects.push(dojo.connect(this.grid.focus, 'move', this, '_swipeByKey'));
+ this._connects.push(dojo.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(dojo.connect(this.grid.views, 'render', this, '_addHeaderSelector'));
+ this._connects.push(dojo.connect(this.grid, 'onSelectionChanged', this, '_onSelectionChanged'));
+ this._connects.push(dojo.connect(this.grid, 'onKeyDown', this, function(e){
+ if(e.rowIndex == -1 && e.cellIndex == this.index && e.keyCode == dojo.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);
+ dojo.stopEvent(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(dojo.isIE){
+ 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; }
+ dojo.stopEvent(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; }
+ dojo.empty(headerCellNode);
+ var g = this.grid;
+ var selector = headerCellNode.appendChild(dojo.create("div", {
+ "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){
+ dojo.disconnect(this._connects[idx]);
+ this._connects.splice(idx, 1);
+ }
+ this._headerSelectorConnectIdx = this._connects.length;
+ this._connects.push(dojo.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; }
+ this._toggleCheckedStyle(-1, this.getValue(-1));
+ },
+ _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);
+ }
+ }
+ }
+});
+
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.IndirectSelection/*name:'indirectSelection'*/, {"preInit": true});
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/IndirectSelection.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/IndirectSelection.xd.js new file mode 100644 index 0000000..8686d02 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/IndirectSelection.xd.js @@ -0,0 +1,623 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.IndirectSelection"],
+["require", 'dojo.string'],
+["require", "dojox.grid.cells.dijit"],
+["require", "dojox.grid.enhanced._Plugin"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.IndirectSelection"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.IndirectSelection"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.IndirectSelection");
+
+dojo.require('dojo.string');
+dojo.require("dojox.grid.cells.dijit");
+dojo.require("dojox.grid.enhanced._Plugin");
+
+dojo.declare("dojox.grid.enhanced.plugins.IndirectSelection", dojox.grid.enhanced._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', dojo.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: dojox.grid.cells.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();
+ }
+
+ dojo.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' ? dojox.grid.cells.SingleRowSelector : dojox.grid.cells.MultipleRowSelector;
+ selectDef = dojo.mixin(defaultCellDef, option, {type: cellType, editable: false, notselectable: true, filterable: false, navigatable: true, nosort: true});
+ dojo.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
+ dojo.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);
+ }
+});
+
+dojo.declare("dojox.grid.cells.RowSelector", dojox.grid.cells._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: '√',
+
+ //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 = dojo.hasClass(dojo.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(dojo.connect(this.grid, 'dokeyup', this, '_dokeyup'));
+ this._connects.push(dojo.connect(this.grid.selection, 'onSelected', this, '_onSelected'));
+ this._connects.push(dojo.connect(this.grid.selection, 'onDeselected', this, '_onDeselected'));
+ this._connects.push(dojo.connect(this.grid.scroller, 'invalidatePageNode', this, '_pageDestroyed'));
+ this._connects.push(dojo.connect(this.grid, 'onCellClick', this, '_onClick'));
+ this._connects.push(dojo.connect(this.grid, 'updateRow', this, '_onUpdateRow'));
+ },
+ formatter: function(data, rowIndex){
+ // summary:
+ // Overwritten, see dojox.grid.cells._Widget
+ 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 = '" + dojo.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 == dojo.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){
+ dojo.toggleClass(selector, this.checkedClass, value);
+ if(this.disabledMap[index]){
+ dojo.toggleClass(selector, this.checkedDisabledClass, value);
+ }
+ dijit.setWaiState(selector, 'pressed', value);
+ if(this.inA11YMode){
+ dojo.attr(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){
+ dojo.toggleClass(selector, this.disabledClass, disabled);
+ if(this.getValue(index)){
+ dojo.toggleClass(selector, this.checkedDisabledClass, disabled);
+ }
+ dijit.setWaiState(selector, '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 = dojo.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;}
+ dojo.destroy(this.map[i]);
+ delete this.map[i];
+ }
+ //console.log("Page ",pageIndex, " destroyed, Map=",this.map);
+ },
+ destroy: function(){
+ for(var i in this.map){
+ dojo.destroy(this.map[i]);
+ delete this.map[i];
+ }
+ for(i in this.disabledMap){ delete this.disabledMap[i]; }
+ dojo.forEach(this._connects, dojo.disconnect);
+ dojo.forEach(this._subscribes, dojo.unsubscribe);
+ delete this._connects;
+ delete this._subscribes;
+ //console.log('Single(Multiple)RowSelector.destroy() executed!');
+ }
+});
+
+dojo.declare("dojox.grid.cells.SingleRowSelector", dojox.grid.cells.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]);
+ }
+});
+
+dojo.declare("dojox.grid.cells.MultipleRowSelector", dojox.grid.cells.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: '□',
+
+ constructor: function(){
+ this._connects.push(dojo.connect(dojo.doc, 'onmouseup', this, '_domouseup'));
+ this._connects.push(dojo.connect(this.grid, 'onRowMouseOver', this, '_onRowMouseOver'));
+ this._connects.push(dojo.connect(this.grid.focus, 'move', this, '_swipeByKey'));
+ this._connects.push(dojo.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(dojo.connect(this.grid.views, 'render', this, '_addHeaderSelector'));
+ this._connects.push(dojo.connect(this.grid, 'onSelectionChanged', this, '_onSelectionChanged'));
+ this._connects.push(dojo.connect(this.grid, 'onKeyDown', this, function(e){
+ if(e.rowIndex == -1 && e.cellIndex == this.index && e.keyCode == dojo.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);
+ dojo.stopEvent(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(dojo.isIE){
+ 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; }
+ dojo.stopEvent(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; }
+ dojo.empty(headerCellNode);
+ var g = this.grid;
+ var selector = headerCellNode.appendChild(dojo.create("div", {
+ "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){
+ dojo.disconnect(this._connects[idx]);
+ this._connects.splice(idx, 1);
+ }
+ this._headerSelectorConnectIdx = this._connects.length;
+ this._connects.push(dojo.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; }
+ this._toggleCheckedStyle(-1, this.getValue(-1));
+ },
+ _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);
+ }
+ }
+ }
+});
+
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.IndirectSelection/*name:'indirectSelection'*/, {"preInit": true});
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Menu.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Menu.js new file mode 100644 index 0000000..bcc09ef --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Menu.js @@ -0,0 +1,131 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.Menu"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Menu"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Menu");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+
+dojo.declare("dojox.grid.enhanced.plugins.Menu", dojox.grid.enhanced._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 = dojo.hitch(g, this.showMenu);
+ g._setRowMenuAttr = dojo.hitch(this, '_setRowMenuAttr');
+ g._setCellMenuAttr = dojo.hitch(this, '_setCellMenuAttr');
+ g._setSelectedRegionMenuAttr = dojo.hitch(this, '_setSelectedRegionMenuAttr');
+ },
+ onStartUp: function(){
+ var type, option = this.option;
+ for(type in option){
+ if(dojo.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;};
+ }
+ }
+ },
+ _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 && dojo.hasClass(e.cellNode, 'dojoxGridRowSelected') ||
+ e.rowNode && (dojo.hasClass(e.rowNode, 'dojoxGridRowSelected') || dojo.hasClass(e.rowNode, 'dojoxGridRowbarSelected')));
+
+ if(inSelectedRegion && this.selectedRegionMenu){
+ this.onSelectedRegionContextMenu(e);
+ return;
+ }
+
+ var info = {target: e.target, coords: e.keyCode !== dojo.keys.F10 && "pageX" in e ? {x: e.pageX, y: e.pageY } : null};
+ if(this.rowMenu && (this.selection.isSelected(e.rowIndex) || e.rowNode && dojo.hasClass(e.rowNode, 'dojoxGridRowbar'))){
+ this.rowMenu._openMyself(info);
+ dojo.stopEvent(e);
+ return;
+ }
+
+ if(this.cellMenu){
+ this.cellMenu._openMyself(info);
+ }
+ dojo.stopEvent(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);
+ }
+});
+
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Menu/*name:'menus'*/);
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Menu.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Menu.xd.js new file mode 100644 index 0000000..fc4f7e1 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Menu.xd.js @@ -0,0 +1,136 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.Menu"],
+["require", "dojox.grid.enhanced._Plugin"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.Menu"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Menu"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Menu");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+
+dojo.declare("dojox.grid.enhanced.plugins.Menu", dojox.grid.enhanced._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 = dojo.hitch(g, this.showMenu);
+ g._setRowMenuAttr = dojo.hitch(this, '_setRowMenuAttr');
+ g._setCellMenuAttr = dojo.hitch(this, '_setCellMenuAttr');
+ g._setSelectedRegionMenuAttr = dojo.hitch(this, '_setSelectedRegionMenuAttr');
+ },
+ onStartUp: function(){
+ var type, option = this.option;
+ for(type in option){
+ if(dojo.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;};
+ }
+ }
+ },
+ _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 && dojo.hasClass(e.cellNode, 'dojoxGridRowSelected') ||
+ e.rowNode && (dojo.hasClass(e.rowNode, 'dojoxGridRowSelected') || dojo.hasClass(e.rowNode, 'dojoxGridRowbarSelected')));
+
+ if(inSelectedRegion && this.selectedRegionMenu){
+ this.onSelectedRegionContextMenu(e);
+ return;
+ }
+
+ var info = {target: e.target, coords: e.keyCode !== dojo.keys.F10 && "pageX" in e ? {x: e.pageX, y: e.pageY } : null};
+ if(this.rowMenu && (this.selection.isSelected(e.rowIndex) || e.rowNode && dojo.hasClass(e.rowNode, 'dojoxGridRowbar'))){
+ this.rowMenu._openMyself(info);
+ dojo.stopEvent(e);
+ return;
+ }
+
+ if(this.cellMenu){
+ this.cellMenu._openMyself(info);
+ }
+ dojo.stopEvent(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);
+ }
+});
+
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Menu/*name:'menus'*/);
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/NestedSorting.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/NestedSorting.js new file mode 100644 index 0000000..f44ff85 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/NestedSorting.js @@ -0,0 +1,579 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.NestedSorting"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.NestedSorting"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.NestedSorting");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+
+dojo.declare("dojox.grid.enhanced.plugins.NestedSorting", dojox.grid.enhanced._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' : '▾',
+ 'dojoxGridAscending' : '▴',
+ 'dojoxGridAscendingTip' : '۸',
+ 'dojoxGridDescendingTip': '۷',
+ 'dojoxGridUnsortedTip' : 'x' //'✖'
+ },
+
+ 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 = dojo.hitch(this, '_setGridSortIndex');
+ this.grid.getSortProps = dojo.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();
+ },
+ 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');
+ },
+ _setGridSortIndex: function(inIndex, inAsc, noRefresh){
+ if(dojo.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();
+ dojo.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;
+ dojo.toggleClass(n, 'dojoxGridSorted', !!len);
+ dojo.toggleClass(n, 'dojoxGridSingleSorted', len === 1);
+ dojo.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 = dojo.query("th", g.viewsHeaderNode).forEach(function(n){
+ idx = parseInt(dojo.attr(n, 'idx'), 10);
+ if(dojo.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
+ var sortNode = dojo.query('.dojoxGridSortNode', node)[0];
+ if(sortNode){
+ dojo.toggleClass(sortNode, 'dojoxGridSortNoWrap', true);
+ }
+ if(dojo.indexOf(this._excludedCoIdx, dojo.attr(node,'idx')) >= 0){
+ dojo.addClass(node, 'dojoxGridNoSort');
+ return;
+ }
+ if(!dojo.query('.dojoxGridSortBtn', node).length){
+ //clear any previous connects
+ this._connects = dojo.filter(this._connects, function(conn){
+ if(conn._sort){
+ dojo.disconnect(conn);
+ return false;
+ }
+ return true;
+ });
+ var n = dojo.create('a', {
+ className: 'dojoxGridSortBtn dojoxGridSortBtnNested',
+ title: this.nls.nestedSort + ' - ' + this.nls.ascending,
+ innerHTML: '1'
+ }, node.firstChild, 'last');
+ var h = this.connect(n, "onmousedown", dojo.stopEvent);
+ h._sort = true;
+ n = dojo.create('a', {
+ className: 'dojoxGridSortBtn dojoxGridSortBtnSingle',
+ title: this.nls.singleSort + ' - ' + this.nls.ascending
+ }, node.firstChild, 'last');
+ h = this.connect(n, "onmousedown", dojo.stopEvent);
+ h._sort = true;
+ }else{
+ //deal with small height grid which doesn't re-render the grid after refresh
+ var a1 = dojo.query('.dojoxGridSortBtnSingle', node)[0];
+ var a2 = dojo.query('.dojoxGridSortBtnNested', node)[0];
+ a1.className = 'dojoxGridSortBtn dojoxGridSortBtnSingle';
+ a2.className = 'dojoxGridSortBtn dojoxGridSortBtnNested';
+ a2.innerHTML = '1';
+ dojo.removeClass(node, 'dojoxGridCellShowIndex');
+ dojo.removeClass(node.firstChild, 'dojoxGridSortNodeSorted');
+ dojo.removeClass(node.firstChild, 'dojoxGridSortNodeAsc');
+ dojo.removeClass(node.firstChild, 'dojoxGridSortNodeDesc');
+ dojo.removeClass(node.firstChild, 'dojoxGridSortNodeMain');
+ dojo.removeClass(node.firstChild, 'dojoxGridSortNodeSub');
+ }
+ this._updateHeaderNodeUI(node);
+ },
+ _onHeaderCellClick: function(e){
+ // summary
+ // See dojox.grid.enhanced._Events._onHeaderCellClick()
+ this._focusRegion(e.target);
+ if(dojo.hasClass(e.target, 'dojoxGridSortBtn')){
+ this._onSortBtnClick(e);
+ dojo.stopEvent(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].index === 0){
+ dojo.addClass(this._headerNodes[p], 'dojoxGridCellShowIndex');
+ break;
+ }
+ }
+ if(!dojo.hasClass(dojo.body(), 'dijit_a11y')){ return; }
+ //a11y support
+ var i = e.cell.index, node = e.cellNode;
+ var singleSortBtn = dojo.query('.dojoxGridSortBtnSingle', node)[0];
+ var nestedSortBtn = dojo.query('.dojoxGridSortBtnNested', node)[0];
+
+ var sortMode = 'none';
+ if(dojo.hasClass(this.grid.domNode, 'dojoxGridSingleSorted')){
+ sortMode = 'single';
+ }else if(dojo.hasClass(this.grid.domNode, 'dojoxGridNestSorted')){
+ sortMode = 'nested';
+ }
+ var nestedIndex = dojo.attr(nestedSortBtn, 'orderIndex');
+ if(nestedIndex === null || nestedIndex === undefined){
+ dojo.attr(nestedSortBtn, '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].index === 0){
+ dojo.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(dojo.hasClass(e.target, 'dojoxGridSortBtnSingle')){
+ this._prepareSingleSort(cellIdx);
+ }else if(dojo.hasClass(e.target, 'dojoxGridSortBtnNested')){
+ this._prepareNestedSort(cellIdx);
+ }else{
+ return;
+ }
+ dojo.stopEvent(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 = dojo.query('.dojoxGridSortNode', node)[0];
+ var singleSortBtn = dojo.query('.dojoxGridSortBtnSingle', node)[0];
+ var nestedSortBtn = dojo.query('.dojoxGridSortBtnNested', node)[0];
+
+ dojo.toggleClass(singleSortBtn, 'dojoxGridSortBtnAsc', this._currMainSort === 'asc');
+ dojo.toggleClass(singleSortBtn, 'dojoxGridSortBtnDesc', this._currMainSort === 'desc');
+ if(this._currMainSort === 'asc'){
+ singleSortBtn.title = this.nls.singleSort + ' - ' + this.nls.descending;
+ }else if(this._currMainSort === 'desc'){
+ singleSortBtn.title = this.nls.singleSort + ' - ' + this.nls.unsorted;
+ }else{
+ singleSortBtn.title = 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;
+
+ dijit.setWaiState(singleSortBtn, 'label', a11ySingleLabel);
+ dijit.setWaiState(nestedSortBtn, 'label', a11yNestedLabel);
+
+ var handles = [
+ _this.connect(singleSortBtn, "onmouseover", function(){
+ dijit.setWaiState(singleSortBtn, 'label', a11ySingleLabelHover);
+ }),
+ _this.connect(singleSortBtn, "onmouseout", function(){
+ dijit.setWaiState(singleSortBtn, 'label', a11ySingleLabel);
+ }),
+ _this.connect(nestedSortBtn, "onmouseover", function(){
+ dijit.setWaiState(nestedSortBtn, 'label', a11yNestedLabelHover);
+ }),
+ _this.connect(nestedSortBtn, "onmouseout", function(){
+ dijit.setWaiState(nestedSortBtn, 'label', a11yNestedLabel);
+ })
+ ];
+ dojo.forEach(handles, function(handle){ handle._sort = true; });
+ }
+ setWaiState();
+
+ var a11y = dojo.hasClass(dojo.body(), "dijit_a11y");
+ if(!data){
+ nestedSortBtn.innerHTML = this._sortDef.length + 1;
+ return;
+ }
+ if(data.index || (data.index === 0 && this._sortDef.length > 1)){
+ nestedSortBtn.innerHTML = data.index + 1;
+ }
+ dojo.addClass(sortNode, 'dojoxGridSortNodeSorted');
+ if(this.isAsc(cellIdx)){
+ dojo.addClass(sortNode, 'dojoxGridSortNodeAsc');
+ nestedSortBtn.title = this.nls.nestedSort + ' - ' + this.nls.descending;
+ if(a11y){sortNode.innerHTML = this._a11yText.dojoxGridAscendingTip;}
+ }else if(this.isDesc(cellIdx)){
+ dojo.addClass(sortNode, 'dojoxGridSortNodeDesc');
+ nestedSortBtn.title = this.nls.nestedSort + ' - ' + this.nls.unsorted;
+ if(a11y){sortNode.innerHTML = this._a11yText.dojoxGridDescendingTip;}
+ }
+ dojo.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: dojo.hitch(this, '_loadNestedSortingProps'),
+ onSave: dojo.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 = dojo.hitch(this, '_focusHeader');
+ area.onBlur = f.blurHeader = f._blurHeader = dojo.hitch(this, '_blurHeader');
+ area.onMove = dojo.hitch(this, '_onMove');
+ area.onKeyDown = dojo.hitch(this, '_onKeyDown');
+ area._regions = [];
+ area.getRegions = null;
+ this.connect(this.grid, 'onBlur', '_blurHeader');
+ }
+ },
+ _focusHeader: function(evt){
+ // 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{
+ dojo.stopEvent(evt);
+ }catch(e){}
+ return true;
+ },
+ _blurHeader: function(evt){
+ this._blurRegion(this._getCurrentRegion());
+ return true;
+ },
+ _onMove: function(rowStep, colStep, evt){
+ var curr = this._currRegionIdx || 0, regions = this._focusRegions;
+ var region = regions[curr + colStep];
+ if(!region){
+ return;
+ }else if(dojo.style(region, 'display') === 'none' || dojo.style(region, 'visibility') === 'hidden'){
+ //if the region is invisible, keep finding next
+ this._onMove(rowStep, colStep + (colStep > 0 ? 1 : -1), evt);
+ 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 dojo.keys.ENTER:
+ case dojo.keys.SPACE:
+ if(dojo.hasClass(e.target, 'dojoxGridSortBtnSingle') ||
+ dojo.hasClass(e.target, 'dojoxGridSortBtnNested')){
+ this._onSortBtnClick(e);
+ }
+ }
+ }
+ },
+ _getRegionView: function(region){
+ var header = region;
+ while(header && !dojo.hasClass(header, 'dojoxGridHeader')){ header = header.parentNode; }
+ if(header){
+ return dojo.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(dojo.style(n, 'display') === 'none'){return;}
+ if(cells[i]['isRowSelector']){
+ regions.push(n);
+ return;
+ }
+ dojo.query('.dojoxGridSortNode,.dojoxGridSortBtnNested,.dojoxGridSortBtnSingle', n)
+ .forEach(function(node){
+ dojo.attr(node, '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);
+ dojo.addClass(header, 'dojoxGridCellSortFocus');
+ if(dojo.hasClass(region, 'dojoxGridSortNode')){
+ dojo.addClass(region, 'dojoxGridSortNodeFocus');
+ }else if(dojo.hasClass(region, 'dojoxGridSortBtn')){
+ dojo.addClass(region, 'dojoxGridSortBtnFocus');
+ }
+ region.focus();
+ this.focus.currentArea('header');
+ this._currRegionIdx = dojo.indexOf(this._focusRegions, region);
+ },
+ _blurRegion: function(region){
+ if(!region){return;}
+ var header = this._getRegionHeader(region);
+ dojo.removeClass(header, 'dojoxGridCellSortFocus');
+ if(dojo.hasClass(region, 'dojoxGridSortNode')){
+ dojo.removeClass(region, 'dojoxGridSortNodeFocus');
+ }else if(dojo.hasClass(region, 'dojoxGridSortBtn')){
+ dojo.removeClass(region, 'dojoxGridSortBtnFocus');
+ }
+ region.blur();
+ },
+ _getCurrentRegion: function(){
+ return this._focusRegions[this._currRegionIdx];
+ },
+ _getRegionHeader: function(region){
+ while(region && !dojo.hasClass(region, 'dojoxGridCell')){
+ region = region.parentNode;
+ }
+ return region;
+ },
+ destroy: function(){
+ this._sortDef = this._sortData = null;
+ this._headerNodes = this._focusRegions = null;
+ this.inherited(arguments);
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.NestedSorting);
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/NestedSorting.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/NestedSorting.xd.js new file mode 100644 index 0000000..3556665 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/NestedSorting.xd.js @@ -0,0 +1,584 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.NestedSorting"],
+["require", "dojox.grid.enhanced._Plugin"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.NestedSorting"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.NestedSorting"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.NestedSorting");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+
+dojo.declare("dojox.grid.enhanced.plugins.NestedSorting", dojox.grid.enhanced._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' : '▾',
+ 'dojoxGridAscending' : '▴',
+ 'dojoxGridAscendingTip' : '۸',
+ 'dojoxGridDescendingTip': '۷',
+ 'dojoxGridUnsortedTip' : 'x' //'✖'
+ },
+
+ 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 = dojo.hitch(this, '_setGridSortIndex');
+ this.grid.getSortProps = dojo.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();
+ },
+ 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');
+ },
+ _setGridSortIndex: function(inIndex, inAsc, noRefresh){
+ if(dojo.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();
+ dojo.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;
+ dojo.toggleClass(n, 'dojoxGridSorted', !!len);
+ dojo.toggleClass(n, 'dojoxGridSingleSorted', len === 1);
+ dojo.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 = dojo.query("th", g.viewsHeaderNode).forEach(function(n){
+ idx = parseInt(dojo.attr(n, 'idx'), 10);
+ if(dojo.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
+ var sortNode = dojo.query('.dojoxGridSortNode', node)[0];
+ if(sortNode){
+ dojo.toggleClass(sortNode, 'dojoxGridSortNoWrap', true);
+ }
+ if(dojo.indexOf(this._excludedCoIdx, dojo.attr(node,'idx')) >= 0){
+ dojo.addClass(node, 'dojoxGridNoSort');
+ return;
+ }
+ if(!dojo.query('.dojoxGridSortBtn', node).length){
+ //clear any previous connects
+ this._connects = dojo.filter(this._connects, function(conn){
+ if(conn._sort){
+ dojo.disconnect(conn);
+ return false;
+ }
+ return true;
+ });
+ var n = dojo.create('a', {
+ className: 'dojoxGridSortBtn dojoxGridSortBtnNested',
+ title: this.nls.nestedSort + ' - ' + this.nls.ascending,
+ innerHTML: '1'
+ }, node.firstChild, 'last');
+ var h = this.connect(n, "onmousedown", dojo.stopEvent);
+ h._sort = true;
+ n = dojo.create('a', {
+ className: 'dojoxGridSortBtn dojoxGridSortBtnSingle',
+ title: this.nls.singleSort + ' - ' + this.nls.ascending
+ }, node.firstChild, 'last');
+ h = this.connect(n, "onmousedown", dojo.stopEvent);
+ h._sort = true;
+ }else{
+ //deal with small height grid which doesn't re-render the grid after refresh
+ var a1 = dojo.query('.dojoxGridSortBtnSingle', node)[0];
+ var a2 = dojo.query('.dojoxGridSortBtnNested', node)[0];
+ a1.className = 'dojoxGridSortBtn dojoxGridSortBtnSingle';
+ a2.className = 'dojoxGridSortBtn dojoxGridSortBtnNested';
+ a2.innerHTML = '1';
+ dojo.removeClass(node, 'dojoxGridCellShowIndex');
+ dojo.removeClass(node.firstChild, 'dojoxGridSortNodeSorted');
+ dojo.removeClass(node.firstChild, 'dojoxGridSortNodeAsc');
+ dojo.removeClass(node.firstChild, 'dojoxGridSortNodeDesc');
+ dojo.removeClass(node.firstChild, 'dojoxGridSortNodeMain');
+ dojo.removeClass(node.firstChild, 'dojoxGridSortNodeSub');
+ }
+ this._updateHeaderNodeUI(node);
+ },
+ _onHeaderCellClick: function(e){
+ // summary
+ // See dojox.grid.enhanced._Events._onHeaderCellClick()
+ this._focusRegion(e.target);
+ if(dojo.hasClass(e.target, 'dojoxGridSortBtn')){
+ this._onSortBtnClick(e);
+ dojo.stopEvent(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].index === 0){
+ dojo.addClass(this._headerNodes[p], 'dojoxGridCellShowIndex');
+ break;
+ }
+ }
+ if(!dojo.hasClass(dojo.body(), 'dijit_a11y')){ return; }
+ //a11y support
+ var i = e.cell.index, node = e.cellNode;
+ var singleSortBtn = dojo.query('.dojoxGridSortBtnSingle', node)[0];
+ var nestedSortBtn = dojo.query('.dojoxGridSortBtnNested', node)[0];
+
+ var sortMode = 'none';
+ if(dojo.hasClass(this.grid.domNode, 'dojoxGridSingleSorted')){
+ sortMode = 'single';
+ }else if(dojo.hasClass(this.grid.domNode, 'dojoxGridNestSorted')){
+ sortMode = 'nested';
+ }
+ var nestedIndex = dojo.attr(nestedSortBtn, 'orderIndex');
+ if(nestedIndex === null || nestedIndex === undefined){
+ dojo.attr(nestedSortBtn, '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].index === 0){
+ dojo.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(dojo.hasClass(e.target, 'dojoxGridSortBtnSingle')){
+ this._prepareSingleSort(cellIdx);
+ }else if(dojo.hasClass(e.target, 'dojoxGridSortBtnNested')){
+ this._prepareNestedSort(cellIdx);
+ }else{
+ return;
+ }
+ dojo.stopEvent(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 = dojo.query('.dojoxGridSortNode', node)[0];
+ var singleSortBtn = dojo.query('.dojoxGridSortBtnSingle', node)[0];
+ var nestedSortBtn = dojo.query('.dojoxGridSortBtnNested', node)[0];
+
+ dojo.toggleClass(singleSortBtn, 'dojoxGridSortBtnAsc', this._currMainSort === 'asc');
+ dojo.toggleClass(singleSortBtn, 'dojoxGridSortBtnDesc', this._currMainSort === 'desc');
+ if(this._currMainSort === 'asc'){
+ singleSortBtn.title = this.nls.singleSort + ' - ' + this.nls.descending;
+ }else if(this._currMainSort === 'desc'){
+ singleSortBtn.title = this.nls.singleSort + ' - ' + this.nls.unsorted;
+ }else{
+ singleSortBtn.title = 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;
+
+ dijit.setWaiState(singleSortBtn, 'label', a11ySingleLabel);
+ dijit.setWaiState(nestedSortBtn, 'label', a11yNestedLabel);
+
+ var handles = [
+ _this.connect(singleSortBtn, "onmouseover", function(){
+ dijit.setWaiState(singleSortBtn, 'label', a11ySingleLabelHover);
+ }),
+ _this.connect(singleSortBtn, "onmouseout", function(){
+ dijit.setWaiState(singleSortBtn, 'label', a11ySingleLabel);
+ }),
+ _this.connect(nestedSortBtn, "onmouseover", function(){
+ dijit.setWaiState(nestedSortBtn, 'label', a11yNestedLabelHover);
+ }),
+ _this.connect(nestedSortBtn, "onmouseout", function(){
+ dijit.setWaiState(nestedSortBtn, 'label', a11yNestedLabel);
+ })
+ ];
+ dojo.forEach(handles, function(handle){ handle._sort = true; });
+ }
+ setWaiState();
+
+ var a11y = dojo.hasClass(dojo.body(), "dijit_a11y");
+ if(!data){
+ nestedSortBtn.innerHTML = this._sortDef.length + 1;
+ return;
+ }
+ if(data.index || (data.index === 0 && this._sortDef.length > 1)){
+ nestedSortBtn.innerHTML = data.index + 1;
+ }
+ dojo.addClass(sortNode, 'dojoxGridSortNodeSorted');
+ if(this.isAsc(cellIdx)){
+ dojo.addClass(sortNode, 'dojoxGridSortNodeAsc');
+ nestedSortBtn.title = this.nls.nestedSort + ' - ' + this.nls.descending;
+ if(a11y){sortNode.innerHTML = this._a11yText.dojoxGridAscendingTip;}
+ }else if(this.isDesc(cellIdx)){
+ dojo.addClass(sortNode, 'dojoxGridSortNodeDesc');
+ nestedSortBtn.title = this.nls.nestedSort + ' - ' + this.nls.unsorted;
+ if(a11y){sortNode.innerHTML = this._a11yText.dojoxGridDescendingTip;}
+ }
+ dojo.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: dojo.hitch(this, '_loadNestedSortingProps'),
+ onSave: dojo.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 = dojo.hitch(this, '_focusHeader');
+ area.onBlur = f.blurHeader = f._blurHeader = dojo.hitch(this, '_blurHeader');
+ area.onMove = dojo.hitch(this, '_onMove');
+ area.onKeyDown = dojo.hitch(this, '_onKeyDown');
+ area._regions = [];
+ area.getRegions = null;
+ this.connect(this.grid, 'onBlur', '_blurHeader');
+ }
+ },
+ _focusHeader: function(evt){
+ // 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{
+ dojo.stopEvent(evt);
+ }catch(e){}
+ return true;
+ },
+ _blurHeader: function(evt){
+ this._blurRegion(this._getCurrentRegion());
+ return true;
+ },
+ _onMove: function(rowStep, colStep, evt){
+ var curr = this._currRegionIdx || 0, regions = this._focusRegions;
+ var region = regions[curr + colStep];
+ if(!region){
+ return;
+ }else if(dojo.style(region, 'display') === 'none' || dojo.style(region, 'visibility') === 'hidden'){
+ //if the region is invisible, keep finding next
+ this._onMove(rowStep, colStep + (colStep > 0 ? 1 : -1), evt);
+ 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 dojo.keys.ENTER:
+ case dojo.keys.SPACE:
+ if(dojo.hasClass(e.target, 'dojoxGridSortBtnSingle') ||
+ dojo.hasClass(e.target, 'dojoxGridSortBtnNested')){
+ this._onSortBtnClick(e);
+ }
+ }
+ }
+ },
+ _getRegionView: function(region){
+ var header = region;
+ while(header && !dojo.hasClass(header, 'dojoxGridHeader')){ header = header.parentNode; }
+ if(header){
+ return dojo.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(dojo.style(n, 'display') === 'none'){return;}
+ if(cells[i]['isRowSelector']){
+ regions.push(n);
+ return;
+ }
+ dojo.query('.dojoxGridSortNode,.dojoxGridSortBtnNested,.dojoxGridSortBtnSingle', n)
+ .forEach(function(node){
+ dojo.attr(node, '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);
+ dojo.addClass(header, 'dojoxGridCellSortFocus');
+ if(dojo.hasClass(region, 'dojoxGridSortNode')){
+ dojo.addClass(region, 'dojoxGridSortNodeFocus');
+ }else if(dojo.hasClass(region, 'dojoxGridSortBtn')){
+ dojo.addClass(region, 'dojoxGridSortBtnFocus');
+ }
+ region.focus();
+ this.focus.currentArea('header');
+ this._currRegionIdx = dojo.indexOf(this._focusRegions, region);
+ },
+ _blurRegion: function(region){
+ if(!region){return;}
+ var header = this._getRegionHeader(region);
+ dojo.removeClass(header, 'dojoxGridCellSortFocus');
+ if(dojo.hasClass(region, 'dojoxGridSortNode')){
+ dojo.removeClass(region, 'dojoxGridSortNodeFocus');
+ }else if(dojo.hasClass(region, 'dojoxGridSortBtn')){
+ dojo.removeClass(region, 'dojoxGridSortBtnFocus');
+ }
+ region.blur();
+ },
+ _getCurrentRegion: function(){
+ return this._focusRegions[this._currRegionIdx];
+ },
+ _getRegionHeader: function(region){
+ while(region && !dojo.hasClass(region, 'dojoxGridCell')){
+ region = region.parentNode;
+ }
+ return region;
+ },
+ destroy: function(){
+ this._sortDef = this._sortData = null;
+ this._headerNodes = this._focusRegions = null;
+ this.inherited(arguments);
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.NestedSorting);
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Pagination.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Pagination.js new file mode 100644 index 0000000..e9b92e1 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Pagination.js @@ -0,0 +1,1235 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.Pagination"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Pagination"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Pagination");
+
+dojo.require("dijit.form.NumberTextBox");
+dojo.require("dijit.form.Button");
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid.enhanced.plugins.Dialog");
+dojo.require("dojox.grid.enhanced.plugins._StoreLayer");
+
+dojo.requireLocalization("dojox.grid.enhanced", "Pagination", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ru,sl,sv,th,tr,zh,zh-tw");
+
+dojo.declare("dojox.grid.enhanced.plugins.Pagination", dojox.grid.enhanced._Plugin, {
+ // summary:
+ // The typical pagination way as an alternative to deal with huge data set besides the default virtual scrolling way
+
+ name: "pagination",
+ // The page size used with the store, default = 25.
+ pageSize: 25,
+
+ defaultRows: 25,
+
+ //current page we are at
+ _currentPage: 0,
+
+ //The currently obtained max # of rows to page through.
+ _maxSize: 0,
+
+ init: function(){
+ this.gh = null;
+ this.grid.rowsPerPage = this.pageSize = this.grid.rowsPerPage ? this.grid.rowsPerPage : this.pageSize;
+ this.grid.usingPagination = true;
+ this.nls = dojo.i18n.getLocalization("dojox.grid.enhanced", "Pagination");
+
+ this._wrapStoreLayer();
+ this._createPaginators(this.option);
+
+ this._regApis();
+ },
+
+ _createPaginators: function(paginationArgs){
+ // summary:
+ // Function to create the pagination control bar.
+ this.paginators = [];
+ if(paginationArgs.position === "both"){
+ this.paginators = [
+ new dojox.grid.enhanced.plugins._Paginator(dojo.mixin(paginationArgs, {position: "bottom", plugin: this})),
+ new dojox.grid.enhanced.plugins._Paginator(dojo.mixin(paginationArgs, {position: "top", plugin: this}))
+ ];
+ }else{
+ this.paginators = [new dojox.grid.enhanced.plugins._Paginator(dojo.mixin(paginationArgs, {plugin: this}))];
+ }
+ },
+
+ _wrapStoreLayer: function(){
+ var g = this.grid,
+ ns = dojox.grid.enhanced.plugins;
+ this._store = g.store;
+ this.query = g.query;
+
+ this.forcePageStoreLayer = new ns._ForcedPageStoreLayer(this);
+ ns.wrap(g, "_storeLayerFetch", this.forcePageStoreLayer);
+
+ this.connect(g, "setQuery", function(query){
+ if(query !== this.query){
+ this.query = query;
+ }
+ });
+ },
+
+ _stopEvent: function(event){
+ try{
+ dojo.stopEvent(event);
+ }catch(e){}
+ },
+
+ _onNew: function(item, parentInfo){
+ var totalPages = Math.ceil(this._maxSize / this.pageSize);
+ if(((this._currentPage + 1 === totalPages || totalPages === 0) && this.grid.rowCount < this.pageSize) || this.showAll){
+ dojo.hitch(this.grid, this._originalOnNew)(item, parentInfo);
+ this.forcePageStoreLayer.endIdx++;
+ }
+ this._maxSize++;
+ if(this.showAll){
+ this.pageSize++;
+ }
+ if(this.showAll && this.grid.autoHeight){
+ this.grid._refresh();
+ }else{
+ dojo.forEach(this.paginators, function(p){
+ p.update();
+ });
+ }
+ },
+
+ _removeSelectedRows: function(){
+ this._multiRemoving = true;
+ this._originalRemove();
+ this._multiRemoving = false;
+ this.grid.resize();
+ this.grid._refresh();
+ },
+
+ _onDelete: function(){
+ if(!this._multiRemoving){
+ this.grid.resize();
+ if(this.showAll){
+ this.grid._refresh();
+ }
+ }
+ if(this.grid.get('rowCount') === 0){
+ this.prevPage();
+ }
+ },
+
+ _regApis: function(){
+ // summary:
+ // register pagination public APIs to grid.
+ var g = this.grid;
+ // New added APIs
+ g.gotoPage = dojo.hitch(this, this.gotoPage);
+ g.nextPage = dojo.hitch(this, this.nextPage);
+ g.prevPage = dojo.hitch(this, this.prevPage);
+ g.gotoFirstPage = dojo.hitch(this, this.gotoFirstPage);
+ g.gotoLastPage = dojo.hitch(this, this.gotoLastPage);
+ g.changePageSize = dojo.hitch(this, this.changePageSize);
+ g.showGotoPageButton = dojo.hitch(this, this.showGotoPageButton);
+ g.getTotalRowCount = dojo.hitch(this, this.getTotalRowCount);
+ // Changed APIs
+ this.originalScrollToRow = dojo.hitch(g, g.scrollToRow);
+ g.scrollToRow = dojo.hitch(this, this.scrollToRow);
+ this._originalOnNew = dojo.hitch(g, g._onNew);
+ this._originalRemove = dojo.hitch(g, g.removeSelectedRows);
+ g.removeSelectedRows = dojo.hitch(this, this._removeSelectedRows);
+ g._onNew = dojo.hitch(this, this._onNew);
+ this.connect(g, "_onDelete", dojo.hitch(this, this._onDelete));
+ },
+
+ destroy: function(){
+ this.inherited(arguments);
+ var g = this.grid;
+ try{
+ dojo.forEach(this.paginators, function(p){
+ p.destroy();
+ });
+ g.unwrap(this.forcePageStoreLayer.name());
+ g._onNew = this._originalOnNew;
+ g.removeSelectedRows = this._originalRemove;
+ g.scrollToRow = this.originalScrollToRow;
+ this.paginators = null;
+ this.nls = null;
+ }catch(e){
+ console.warn("Pagination.destroy() error: ", e);
+ }
+ },
+
+ nextPage: function(){
+ // summary:
+ // Function to handle shifting to the next page in the list.
+ if(this._maxSize > ((this._currentPage + 1) * this.pageSize)){
+ //Current page is indexed at 0 and gotoPage expects 1-X. So to go
+ //up one, pass current page + 2!
+ this.gotoPage(this._currentPage + 2);
+ }
+ },
+
+ prevPage: function(){
+ // summary:
+ // Function to handle shifting to the previous page in the list.
+ if(this._currentPage > 0){
+ //Current page is indexed at 0 and gotoPage expects 1-X. So to go
+ //back one, pass current page!
+ this.gotoPage(this._currentPage);
+ }
+ },
+
+ gotoPage: function(page){
+ // summary:
+ // Function to handle shifting to an arbirtary page in the list.
+ // page:
+ // The page to go to, starting at 1.
+ var totalPages = Math.ceil(this._maxSize / this.pageSize);
+ page--;
+ if(page < totalPages && page >= 0 && this._currentPage !== page){
+ this._currentPage = page;
+ // this._updateSelected();
+ this.grid.setQuery(this.query);
+ this.grid.resize();
+ }
+ },
+
+ gotoFirstPage: function(){
+ // summary:
+ // Go to the first page
+ this.gotoPage(1);
+ },
+
+ gotoLastPage: function(){
+ // summary:
+ // Go to the last page
+ var totalPages = Math.ceil(this._maxSize / this.pageSize);
+ this.gotoPage(totalPages);
+ },
+
+ changePageSize: function(size){
+ // summary:
+ // Change size of items per page.
+ // This function will only be called by _Paginator
+ if(typeof size == "string"){
+ size = parseInt(size, 10);
+ }
+ var startIndex = this.pageSize * this._currentPage;
+ dojo.forEach(this.paginators, function(f){
+ f.currentPageSize = this.grid.rowsPerPage = this.pageSize = size;
+ if(size >= this._maxSize){
+ this.grid.rowsPerPage = this.defaultRows;
+ this.grid.usingPagination = false;
+ }else{
+ this.grid.usingPagination = true;
+ }
+ }, this);
+ var endIndex = startIndex + Math.min(this.pageSize, this._maxSize);
+ if(endIndex > this._maxSize){
+ this.gotoLastPage();
+ }else{
+ var cp = Math.ceil(startIndex / this.pageSize);
+ if(cp !== this._currentPage){
+ this.gotoPage(cp + 1);
+ }else{
+ this.grid._refresh(true);
+ }
+ }
+ this.grid.resize();
+ },
+
+ 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
+ dojo.forEach(this.paginators, function(p){
+ p._showGotoButton(flag);
+ });
+ },
+
+ 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.pageSize, 10),
+ totalPages = Math.ceil(this._maxSize / this.pageSize);
+ if(page > totalPages){
+ return;
+ }
+ this.gotoPage(page + 1);
+ var rowIdx = inRowIndex % this.pageSize;
+ this.grid.setScrollTop(this.grid.scroller.findScrollTop(rowIdx) + 1);
+ },
+
+ getTotalRowCount: function(){
+ // summary:
+ // Function for get total row count
+ return this._maxSize;
+ }
+});
+
+dojo.declare("dojox.grid.enhanced.plugins._ForcedPageStoreLayer", dojox.grid.enhanced.plugins._StoreLayer, {
+ tags: ["presentation"],
+
+ constructor: function(plugin){
+ this._plugin = plugin;
+ },
+
+ _fetch: function(request){
+ var self = this,
+ plugin = self._plugin,
+ grid = plugin.grid,
+ scope = request.scope || dojo.global,
+ onBegin = request.onBegin;
+
+ request.start = plugin._currentPage * plugin.pageSize + request.start;
+ self.startIdx = request.start;
+ self.endIdx = request.start + plugin.pageSize - 1;
+ if(onBegin && (plugin.showAll || dojo.every(plugin.paginators, function(p){
+ return plugin.showAll = !p.sizeSwitch && !p.pageStepper && !p.gotoButton;
+ }))){
+ request.onBegin = function(size, req){
+ plugin._maxSize = plugin.pageSize = size;
+ self.startIdx = 0;
+ self.endIdx = size - 1;
+ dojo.forEach(plugin.paginators, function(f){
+ f.update();
+ });
+ req.onBegin = onBegin;
+ req.onBegin.call(scope, size, req);
+ };
+ }else if(onBegin){
+ request.onBegin = function(size, req){
+ req.start = 0;
+ req.count = plugin.pageSize;
+ plugin._maxSize = size;
+ self.endIdx = self.endIdx > size ? (size - 1) : self.endIdx;
+ if(self.startIdx > size && size !== 0){
+ grid._pending_requests[req.start] = false;
+ plugin.gotoFirstPage();
+ }
+ dojo.forEach(plugin.paginators, function(f){
+ f.update();
+ });
+ req.onBegin = onBegin;
+ req.onBegin.call(scope, Math.min(plugin.pageSize, (size - self.startIdx)), req);
+ };
+ }
+ return dojo.hitch(this._store, this._originFetch)(request);
+ }
+});
+
+dojo.declare("dojox.grid.enhanced.plugins._Paginator", [dijit._Widget,dijit._Templated], {
+ templateString:"<div dojoAttachPoint=\"paginatorBar\">\r\n\t<table cellpadding=\"0\" cellspacing=\"0\" class=\"dojoxGridPaginator\">\r\n\t\t<tr>\r\n\t\t\t<td dojoAttachPoint=\"descriptionTd\" class=\"dojoxGridDescriptionTd\">\r\n\t\t\t\t<div dojoAttachPoint=\"descriptionDiv\" class=\"dojoxGridDescription\" />\r\n\t\t\t</td>\r\n\t\t\t<td dojoAttachPoint=\"sizeSwitchTd\"></td>\r\n\t\t\t<td dojoAttachPoint=\"pageStepperTd\" class=\"dojoxGridPaginatorFastStep\">\r\n\t\t\t\t<div dojoAttachPoint=\"pageStepperDiv\" class=\"dojoxGridPaginatorStep\"></div>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n\t</table>\r\n</div>\r\n",
+
+ // pagination bar position - "bottom"|"top"
+ position: "bottom",
+
+ // max data item size
+ _maxItemSize: 0,
+
+ // description message status params
+ description: true,
+
+ // fast step page status params
+ pageStepper: true,
+
+ maxPageStep: 7,
+
+ // items per page size switch params
+ sizeSwitch: true,
+
+ pageSizes: ["10", "25", "50", "100", "All"],
+
+ gotoButton: false,
+
+ constructor: function(params){
+ dojo.mixin(this, params);
+ this.grid = this.plugin.grid;
+ this.itemTitle = this.itemTitle ? this.itemTitle : this.plugin.nls.itemTitle;
+ this.descTemplate = this.descTemplate ? this.descTemplate : this.plugin.nls.descTemplate;
+ },
+
+ postCreate: function(){
+ this.inherited(arguments);
+ this._setWidthValue();
+ var self = this;
+ var g = this.grid;
+ this.plugin.connect(g, "_resize", dojo.hitch(this, "_resetGridHeight"));
+ this._originalResize = dojo.hitch(g, "resize");
+ g.resize = function(changeSize, resultSize){
+ self._changeSize = g._pendingChangeSize = changeSize;
+ self._resultSize = g._pendingResultSize = resultSize;
+ g.sizeChange();
+ };
+ this._placeSelf();
+ },
+
+ destroy: function(){
+ this.inherited(arguments);
+ this.grid.focus.removeArea("pagination" + this.position.toLowerCase());
+ if(this._gotoPageDialog){
+ this._gotoPageDialog.destroy();
+ dojo.destroy(this.gotoPageTd);
+ delete this.gotoPageTd;
+ delete this._gotoPageDialog;
+ }
+ this.grid.resize = this._originalResize;
+ this.pageSizes = null;
+ },
+
+ update: function(){
+ // summary:
+ // Function to update paging information and update
+ // pagination bar display.
+ this.currentPageSize = this.plugin.pageSize;
+ this._maxItemSize = this.plugin._maxSize;
+
+ // update pagination bar display information
+ this._updateDescription();
+ this._updatePageStepper();
+ this._updateSizeSwitch();
+ this._updateGotoButton();
+ },
+
+ _setWidthValue: function(){
+ var type = ["description", "sizeSwitch", "pageStepper"];
+ var endWith = function(str1, str2){
+ var reg = new RegExp(str2+"$");
+ return reg.test(str1);
+ };
+ dojo.forEach(type, function(t){
+ var width, flag = this[t];
+ if(flag === undefined || typeof flag == "boolean"){
+ return;
+ }
+ if(dojo.isString(flag)){
+ width = endWith(flag, "px") || endWith(flag, "%") || endWith(flag, "em") ? flag : parseInt(flag, 10) > 0 ? parseInt(flag, 10) + "px" : null;
+ }else if(typeof flag === "number" && flag > 0){
+ width = flag + "px";
+ }
+ this[t] = width ? true : false;
+ this[t + "Width"] = width;
+ }, this);
+ },
+
+ _regFocusMgr: function(position){
+ // summary:
+ // Function to register pagination bar to focus manager.
+ this.grid.focus.addArea({
+ name: "pagination" + position,
+ onFocus: dojo.hitch(this, this._onFocusPaginator),
+ onBlur: dojo.hitch(this, this._onBlurPaginator),
+ onMove: dojo.hitch(this, this._moveFocus),
+ onKeyDown: dojo.hitch(this, this._onKeyDown)
+ });
+ switch(position){
+ case "top":
+ this.grid.focus.placeArea("pagination" + position, "before", "header");
+ break;
+ case "bottom":
+ default:
+ this.grid.focus.placeArea("pagination" + position, "after", "content");
+ break;
+ }
+ },
+
+ _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;
+ var position = dojo.trim(this.position.toLowerCase());
+ switch(position){
+ case "top":
+ this.placeAt(g.viewsHeaderNode, "before");
+ this._regFocusMgr("top");
+ break;
+ case "bottom":
+ default:
+ this.placeAt(g.viewsNode, "after");
+ this._regFocusMgr("bottom");
+ break;
+ }
+ },
+
+ _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 = dojo.contentBox(g.domNode).h + 2 * padBorder;
+ }
+ if(resultSize){
+ changeSize = resultSize;
+ }
+ if(changeSize){
+ this.plugin.gh = dojo.contentBox(g.domNode).h + 2 * padBorder;
+ }
+ var gh = this.plugin.gh,
+ hh = g._getHeaderHeight(),
+ ph = dojo.marginBox(this.domNode).h;
+ ph = this.plugin.paginators[1] ? ph * 2 : ph;
+ if(typeof g.autoHeight == "number"){
+ var cgh = gh + ph - padBorder;
+ dojo.style(g.domNode, "height", cgh + "px");
+ dojo.style(g.viewsNode, "height", (cgh - ph - hh) + "px");
+
+ this._styleMsgNode(hh, dojo.marginBox(g.viewsNode).w, cgh - ph - hh);
+ }else{
+ var h = gh - ph - hh - padBorder;
+ dojo.style(g.viewsNode, "height", h + "px");
+ var hasHScroller = dojo.some(g.views.views, function(v){
+ return v.hasHScrollbar();
+ });
+ dojo.forEach(g.viewsNode.childNodes, function(c, idx){
+ dojo.style(c, "height", h + "px");
+ });
+ dojo.forEach(g.views.views, function(v, idx){
+ if(v.scrollboxNode){
+ if(!v.hasHScrollbar() && hasHScroller){
+ dojo.style(v.scrollboxNode, "height", (h - dojox.html.metrics.getScrollbar().h) + "px");
+ }else{
+ dojo.style(v.scrollboxNode, "height", h + "px");
+ }
+ }
+ });
+ this._styleMsgNode(hh, dojo.marginBox(g.viewsNode).w, h);
+ }
+ },
+
+ _styleMsgNode: function(top, width, height){
+ var messagesNode = this.grid.messagesNode;
+ dojo.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;
+ if(this.description && this.descriptionDiv){
+ this.descriptionDiv.innerHTML = this._maxItemSize > 0 ? dojo.string.substitute(this.descTemplate, [this.itemTitle, this._maxItemSize, s.startIdx + 1, s.endIdx + 1]) : "0 " + this.itemTitle;
+ }
+ if(this.descriptionWidth){
+ dojo.style(this.descriptionTd, "width", this.descriptionWidth);
+ }
+ },
+
+ _updateSizeSwitch: function(){
+ // summary:
+ // Update "items per page" information.
+ if(!this.sizeSwitchTd){
+ return;
+ }
+ if(!this.sizeSwitch || this._maxItemSize <= 0){
+ dojo.style(this.sizeSwitchTd, "display", "none");
+ return;
+ }else{
+ dojo.style(this.sizeSwitchTd, "display", "");
+ }
+ if(this.initializedSizeNode && !this.pageSizeValue){
+ // do not update page size if page size was not changed
+ return;
+ }
+ if(this.sizeSwitchTd.childNodes.length < 1){
+ this._createSizeSwitchNodes();
+ }
+ this._updateSwitchNodeClass();
+
+ // move focus to next activable node
+ this._moveToNextActivableNode(this._getAllPageSizeNodes(), this.pageSizeValue);
+ this.pageSizeValue = null;
+ },
+
+ _createSizeSwitchNodes: function(){
+ // summary:
+ // The function to create the size switch nodes
+ var node = null;
+ if(!this.pageSizes || this.pageSizes.length < 1){
+ return;
+ }
+ dojo.forEach(this.pageSizes, function(size){
+ // create page size switch node
+ size = dojo.trim(size);
+ var labelValue = size.toLowerCase() == "all" ? this.plugin.nls.allItemsLabelTemplate : dojo.string.substitute(this.plugin.nls.pageSizeLabelTemplate, [size]);
+ node = dojo.create("span", {innerHTML: size, title: labelValue, value: size, tabindex: 0}, this.sizeSwitchTd, "last");
+ // for accessibility
+ dijit.setWaiState(node, "label", labelValue);
+ // connect event
+ this.plugin.connect(node, "onclick", dojo.hitch(this, "_onSwitchPageSize"));
+ this.plugin.connect(node, "onmouseover", function(e){
+ dojo.addClass(e.target, "dojoxGridPageTextHover");
+ });
+ this.plugin.connect(node, "onmouseout", function(e){
+ dojo.removeClass(e.target, "dojoxGridPageTextHover");
+ });
+ // create a separation node
+ node = dojo.create("span", {innerHTML: "|"}, this.sizeSwitchTd, "last");
+ dojo.addClass(node, "dojoxGridSeparator");
+ }, this);
+ // delete last separation node
+ dojo.destroy(node);
+ this.initializedSizeNode = true;
+ if(this.sizeSwitchWidth){
+ dojo.style(this.sizeSwitchTd, "width", this.sizeSwitchWidth);
+ }
+ },
+
+ _updateSwitchNodeClass: function(){
+ // summary:
+ // Update the switch nodes style
+ var size = null;
+ var hasActivedNode = false;
+ var styleNode = function(node, status){
+ if(status){
+ dojo.addClass(node, "dojoxGridActivedSwitch");
+ dojo.attr(node, "tabindex", "-1");
+ hasActivedNode = true;
+ }else{
+ dojo.addClass(node, "dojoxGridInactiveSwitch");
+ dojo.attr(node, "tabindex", "0");
+ }
+ };
+ dojo.forEach(this.sizeSwitchTd.childNodes, function(node){
+ if(node.value){
+ size = node.value;
+ dojo.removeClass(node);
+ if(this.pageSizeValue){
+ styleNode(node, size === this.pageSizeValue && !hasActivedNode);
+ }else{
+ if(size.toLowerCase() == "all"){
+ size = this._maxItemSize;
+ }
+ styleNode(node, this.currentPageSize === parseInt(size, 10) && !hasActivedNode);
+ }
+ }
+ }, this);
+ },
+
+ _updatePageStepper: function(){
+ // summary:
+ // Update the page step nodes
+ if(!this.pageStepperTd){
+ return;
+ }
+ if(!this.pageStepper || this._maxItemSize <= 0){
+ dojo.style(this.pageStepperTd, "display", "none");
+ return;
+ }else{
+ dojo.style(this.pageStepperTd, "display", "");
+ }
+ if(this.pageStepperDiv.childNodes.length < 1){
+ this._createPageStepNodes();
+ this._createWardBtns();
+ }else{
+ this._resetPageStepNodes();
+ }
+ this._updatePageStepNodeClass();
+
+ this._moveToNextActivableNode(this._getAllPageStepNodes(), this.pageStepValue);
+ this.pageStepValue = null;
+ },
+
+ _createPageStepNodes: function(){
+ // summary:
+ // Create the page step nodes if they do not exist
+ var startPage = this._getStartPage(),
+ stepSize = this._getStepPageSize(),
+ label = "",
+ node = null;
+ for(var i = startPage; i < this.maxPageStep + 1; i++){
+ label = dojo.string.substitute(this.plugin.nls.pageStepLabelTemplate, [i + ""]);
+ node = dojo.create("div", {innerHTML: i, value: i, title: label, tabindex: i < startPage + stepSize ? 0 : -1}, this.pageStepperDiv, "last");
+ dijit.setWaiState(node, "label", label);
+ // connect event
+ this.plugin.connect(node, "onclick", dojo.hitch(this, "_onPageStep"));
+ this.plugin.connect(node, "onmouseover", function(e){
+ dojo.addClass(e.target, "dojoxGridPageTextHover");
+ });
+ this.plugin.connect(node, "onmouseout", function(e){
+ dojo.removeClass(e.target, "dojoxGridPageTextHover");
+ });
+ dojo.style(node, "display", i < startPage + stepSize ? "block" : "none");
+ }
+ if(this.pageStepperWidth){
+ dojo.style(this.pageStepperTd, "width", this.pageStepperWidth);
+ }
+ },
+
+ _createWardBtns: function(){
+ // summary:
+ // Create the previous/next/first/last button
+ var self = this;
+ var highContrastLabel = {prevPage: "<", firstPage: "«", nextPage: ">", lastPage: "»"};
+ var createWardBtn = function(value, label, position){
+ var node = dojo.create("div", {value: value, title: label, tabindex: 1}, self.pageStepperDiv, position);
+ self.plugin.connect(node, "onclick", dojo.hitch(self, "_onPageStep"));
+ dijit.setWaiState(node, "label", label);
+ // for high contrast
+ var highConrastNode = dojo.create("span", {value: value, title: label, innerHTML: highContrastLabel[value]}, node, position);
+ dojo.addClass(highConrastNode, "dojoxGridWardButtonInner");
+ };
+ createWardBtn("prevPage", this.plugin.nls.prevTip, "first");
+ createWardBtn("firstPage", this.plugin.nls.firstTip, "first");
+ createWardBtn("nextPage", this.plugin.nls.nextTip, "last");
+ createWardBtn("lastPage", this.plugin.nls.lastTip, "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;
+ for(var i = startPage, j = 2; j < stepNodes.length - 2; j++, i++){
+ node = stepNodes[j];
+ if(i < startPage + stepSize){
+ dojo.attr(node, "innerHTML", i);
+ dojo.attr(node, "value", i);
+ dojo.style(node, "display", "block");
+ dijit.setWaiState(node, "label", dojo.string.substitute(this.plugin.nls.pageStepLabelTemplate, [i + ""]));
+ }else{
+ dojo.style(node, "display", "none");
+ }
+ }
+ },
+
+ _updatePageStepNodeClass: function(){
+ // summary:
+ // Update the style of the page step nodes
+ var value = null,
+ curPage = this._getCurrentPageNo(),
+ pageCount = this._getPageCount(),
+ visibleNodeLen = 0;
+
+ var updateClass = function(node, isWardBtn, status){
+ var value = node.value,
+ enableClass = isWardBtn ? "dojoxGrid" + value + "Btn" : "dojoxGridInactived",
+ disableClass = isWardBtn ? "dojoxGrid" + value + "BtnDisable" : "dojoxGridActived";
+ if(status){
+ dojo.addClass(node, disableClass);
+ dojo.attr(node, "tabindex", "-1");
+ }else{
+ dojo.addClass(node, enableClass);
+ dojo.attr(node, "tabindex", "0");
+ }
+ };
+ dojo.forEach(this.pageStepperDiv.childNodes, function(node){
+ dojo.removeClass(node);
+ if(isNaN(parseInt(node.value, 10))){
+ dojo.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 || dojo.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.gotoPageTd){
+ if(this._gotoPageDialog){
+ this._gotoPageDialog.destroy();
+ }
+ dojo.destroy(this.gotoPageDiv);
+ dojo.destroy(this.gotoPageTd);
+ delete this.gotoPageDiv;
+ delete this.gotoPageTd;
+ }
+ return;
+ }
+ if(!this.gotoPageTd){
+ this._createGotoNode();
+ }
+ dojo.toggleClass(this.gotoPageDiv, "dojoxGridPaginatorGotoDivDisabled", this.plugin.pageSize >= this.plugin._maxSize);
+ },
+
+ _createGotoNode: function(){
+ // summary:
+ // Create the goto page button
+ this.gotoPageTd = dojo.create("td", {}, dojo.query("tr", this.domNode)[0], "last");
+ dojo.addClass(this.gotoPageTd, "dojoxGridPaginatorGotoTd");
+ this.gotoPageDiv = dojo.create("div", {tabindex: "0", title: this.plugin.nls.gotoButtonTitle}, this.gotoPageTd, "first");
+ dojo.addClass(this.gotoPageDiv, "dojoxGridPaginatorGotoDiv");
+ this.plugin.connect(this.gotoPageDiv, "onclick", dojo.hitch(this, "_openGotopageDialog"));
+ // for high contrast
+ var highConrastNode = dojo.create("span", {title: this.plugin.nls.gotoButtonTitle, innerHTML: "⊥"}, this.gotoPageDiv, "last");
+ dojo.addClass(highConrastNode, "dojoxGridWardButtonInner");
+ },
+
+ _openGotopageDialog: function(event){
+ // summary:
+ // Show the goto page dialog
+ if(!this._gotoPageDialog){
+ this._gotoPageDialog = new dojox.grid.enhanced.plugins.pagination._GotoPageDialog(this.plugin);
+ }
+ // focus
+ if(!this._currentFocusNode){
+ this.grid.focus.focusArea("pagination" + this.position, event);
+ }else{
+ this._currentFocusNode = this.gotoPageDiv;
+ }
+ if(this.focusArea != "pageStep"){
+ this.focusArea = "pageStep";
+ }
+ this._gotoPageDialog.updatePageCount();
+ this._gotoPageDialog.showDialog();
+ },
+
+ // ===== focus handlers ===== //
+ _onFocusPaginator: function(event, step){
+ // summary:
+ // Focus handler
+ if(!this._currentFocusNode){
+ if(step > 0){
+ return this._onFocusPageSizeNode(event) ? true : this._onFocusPageStepNode(event);
+ }else if(step < 0){
+ return this._onFocusPageStepNode(event) ? true : this._onFocusPageSizeNode(event);
+ }else{
+ return false;
+ }
+ }else{
+ if(step > 0){
+ return this.focusArea === "pageSize" ? this._onFocusPageStepNode(event) : false;
+ }else if(step < 0){
+ return this.focusArea === "pageStep" ? this._onFocusPageSizeNode(event) : false;
+ }else{
+ return false;
+ }
+ }
+ },
+
+ _onFocusPageSizeNode: function(event){
+ // summary:
+ // Focus the page size area, if there is no focusable node, return false
+ var pageSizeNodes = this._getPageSizeActivableNodes();
+ if(event && event.type !== "click"){
+ if(pageSizeNodes[0]){
+ dijit.focus(pageSizeNodes[0]);
+ this._currentFocusNode = pageSizeNodes[0];
+ this.focusArea = "pageSize";
+ this.plugin._stopEvent(event);
+ return true;
+ }else{
+ return false;
+ }
+ }
+ if(event && event.type == "click"){
+ if(dojo.indexOf(this._getPageSizeActivableNodes(), event.target) > -1){
+ this.focusArea = "pageSize";
+ this.plugin._stopEvent(event);
+ return true;
+ }
+ }
+ return false;
+ },
+
+ _onFocusPageStepNode: function(event){
+ // summary:
+ // Focus the page step area, if there is no focusable node, return false
+ var pageStepNodes = this._getPageStepActivableNodes();
+ if(event && event.type !== "click"){
+ if(pageStepNodes[0]){
+ dijit.focus(pageStepNodes[0]);
+ this._currentFocusNode = pageStepNodes[0];
+ this.focusArea = "pageStep";
+ this.plugin._stopEvent(event);
+ return true;
+ }else if(this.gotoPageDiv){
+ dijit.focus(this.gotoPageDiv);
+ this._currentFocusNode = this.gotoPageDiv;
+ this.focusArea = "pageStep";
+ this.plugin._stopEvent(event);
+ return true;
+ }else{
+ return false;
+ }
+ }
+ if(event && event.type == "click"){
+ if(dojo.indexOf(this._getPageStepActivableNodes(), event.target) > -1){
+ this.focusArea = "pageStep";
+ this.plugin._stopEvent(event);
+ return true;
+ }else if(event.target == this.gotoPageDiv){
+ dijit.focus(this.gotoPageDiv);
+ this._currentFocusNode = this.gotoPageDiv;
+ this.focusArea = "pageStep";
+ this.plugin._stopEvent(event);
+ return true;
+ }
+ }
+ return false;
+ },
+
+ _onFocusGotoPageNode: function(event){
+ // summary:
+ // Focus the goto page button, if there is no focusable node, return false
+ if(!this.gotoButton || !this.gotoPageTd){
+ return false;
+ }
+ if(event && event.type !== "click" || (event.type == "click" && event.target == this.gotoPageDiv)){
+ dijit.focus(this.gotoPageDiv);
+ this._currentFocusNode = this.gotoPageDiv;
+ this.focusArea = "gotoButton";
+ this.plugin._stopEvent(event);
+ return true;
+ }
+ return true;
+ },
+
+ _onBlurPaginator: function(event, step){
+ var pageSizeNodes = this._getPageSizeActivableNodes(),
+ pageStepNodes = this._getPageStepActivableNodes();
+
+ if(step > 0 && this.focusArea === "pageSize" && (pageStepNodes.length > 1 || this.gotoButton)){
+ return false;
+ }else if(step < 0 && this.focusArea === "pageStep" && pageSizeNodes.length > 1){
+ return false;
+ }
+ this._currentFocusNode = null;
+ this.focusArea = null;
+ return true;
+ },
+
+ _onKeyDown: function(event, isBubble){
+ // summary:
+ // Focus navigation
+ if(isBubble){
+ return;
+ }
+ if(event.altKey || event.metaKey){
+ return;
+ }
+ var dk = dojo.keys;
+ if(event.keyCode === dk.ENTER || event.keyCode === dk.SPACE){
+ if(dojo.indexOf(this._getPageStepActivableNodes(), this._currentFocusNode) > -1){
+ this._onPageStep(event);
+ }else if(dojo.indexOf(this._getPageSizeActivableNodes(), this._currentFocusNode) > -1){
+ this._onSwitchPageSize(event);
+ }else if(this._currentFocusNode === this.gotoPageDiv){
+ this._openGotopageDialog(event);
+ }
+ }
+ this.plugin._stopEvent(event);
+ },
+
+ _moveFocus: function(rowDelta, colDelta, evt){
+ // summary:
+ // Move focus according row delta&column delta
+ var nodes;
+ if(this.focusArea == "pageSize"){
+ nodes = this._getPageSizeActivableNodes();
+ }else if(this.focusArea == "pageStep"){
+ nodes = this._getPageStepActivableNodes();
+ if(this.gotoPageDiv){
+ nodes.push(this.gotoPageDiv);
+ }
+ }
+ if(nodes.length < 1){
+ return;
+ }
+ var currentIdx = dojo.indexOf(nodes, this._currentFocusNode);
+ var focusIdx = currentIdx + colDelta;
+ if(focusIdx >= 0 && focusIdx < nodes.length){
+ dijit.focus(nodes[focusIdx]);
+ this._currentFocusNode = nodes[focusIdx];
+ }
+ this.plugin._stopEvent(evt);
+ },
+
+ _getPageSizeActivableNodes: function(){
+ return dojo.query("span[tabindex='0']", this.sizeSwitchTd);
+ },
+
+ _getPageStepActivableNodes: function(){
+ return (dojo.query("div[tabindex='0']", this.pageStepperDiv));
+ },
+
+ _getAllPageSizeNodes: function(){
+ var nodeList = [];
+ dojo.forEach(this.sizeSwitchTd.childNodes, function(node){
+ if(node.value){
+ nodeList.push(node);
+ }
+ });
+ return nodeList;
+ },
+
+ _getAllPageStepNodes: function(){
+ var nodeList = [];
+ for(var i = 0, len = this.pageStepperDiv.childNodes.length; i < len; i++){
+ nodeList.push(this.pageStepperDiv.childNodes[i]);
+ }
+ return nodeList;
+ },
+
+ _moveToNextActivableNode: function(nodeList, curNodeValue){
+ // summary:
+ // Need to move the focus to next node since current node is inactive and unfocusable
+ if(!curNodeValue){
+ return;
+ }
+ if(nodeList.length < 2){
+ this.grid.focus.tab(1);
+ }
+ var nl = [],
+ node = null,
+ index = 0;
+ dojo.forEach(nodeList, function(n){
+ if(n.value == curNodeValue){
+ nl.push(n);
+ node = n;
+ }else if(dojo.attr(n, "tabindex") == "0"){
+ nl.push(n);
+ }
+ });
+ if(nl.length < 2){
+ this.grid.focus.tab(1);
+ }
+ index = dojo.indexOf(nl, node);
+ if(dojo.attr(node, "tabindex") != "0"){
+ node = nl[index + 1] ? nl[index + 1] : nl[index - 1];
+ }
+ dijit.focus(node);
+ this._currentFocusNode = node;
+ },
+
+ // ===== pagination events handlers ===== //
+ _onSwitchPageSize: function(/*Event*/e){
+ // summary:
+ // The handler of switch the page size
+ var size = this.pageSizeValue = e.target.value;
+ if(!size){
+ return;
+ }
+ if(dojo.trim(size.toLowerCase()) == "all"){
+ size = this._maxItemSize;
+ }
+ this.plugin.showAll = parseInt(size, 10) >= this._maxItemSize ? true : false;
+ this.plugin.grid.usingPagination = !this.plugin.showAll;
+
+ size = parseInt(size, 10);
+ if(isNaN(size) || size <= 0/* || size == this.currentPageSize*/){
+ return;
+ }
+
+ if(!this._currentFocusNode){
+ this.grid.focus.currentArea("pagination" + this.position);
+ }
+ if(this.focusArea != "pageSize"){
+ this.focusArea = "pageSize";
+ }
+ this.plugin.changePageSize(size);
+ },
+
+ _onPageStep: function(/*Event*/e){
+ // summary:
+ // The handler jump page event
+ var p = this.plugin,
+ value = this.pageStepValue = e.target.value;
+
+ if(!this._currentFocusNode){
+ this.grid.focus.currentArea("pagination" + this.position);
+ }
+ if(this.focusArea != "pageStep"){
+ this.focusArea = "pageStep";
+ }
+ if(!isNaN(parseInt(value, 10))){
+ p.gotoPage(value);
+ }else{
+ switch(e.target.value){
+ case "prevPage":
+ p.prevPage();
+ break;
+ case "nextPage":
+ p.nextPage();
+ break;
+ case "firstPage":
+ p.gotoFirstPage();
+ break;
+ case "lastPage":
+ p.gotoLastPage();
+ }
+ }
+ },
+
+ // ===== information getters ===== //
+ _getCurrentPageNo: function(){
+ return this.plugin._currentPage + 1;
+ },
+
+ _getPageCount: function(){
+ if(!this._maxItemSize || !this.currentPageSize){
+ return 0;
+ }
+ return Math.ceil(this._maxItemSize / this.currentPageSize);
+ },
+
+ _getStartPage: function(){
+ var cp = this._getCurrentPageNo();
+ var ms = parseInt(this.maxPageStep / 2, 10);
+ var pc = this._getPageCount();
+ if(cp < ms || (cp - ms) < 1){
+ return 1;
+ }else if(pc <= this.maxPageStep){
+ return 1;
+ }else{
+ if(pc - cp < ms && cp - this.maxPageStep >= 0){
+ return pc - this.maxPageStep + 1;
+ }else{
+ return (cp - ms);
+ }
+ }
+ },
+
+ _getStepPageSize: function(){
+ var sp = this._getStartPage();
+ var count = this._getPageCount();
+ if((sp + this.maxPageStep) > count){
+ return count - sp + 1;
+ }else{
+ return this.maxPageStep;
+ }
+ }
+
+});
+
+dojo.declare("dojox.grid.enhanced.plugins.pagination._GotoPageDialog", null, {
+
+ pageCount: 0,
+
+ constructor: function(plugin){
+ this.plugin = plugin;
+ this.pageCount = this.plugin.paginators[0]._getPageCount();
+ this._dialogNode = dojo.create("div", {}, dojo.body(), "last");
+ this._gotoPageDialog = new dojox.grid.enhanced.plugins.Dialog({
+ "refNode": plugin.grid.domNode,
+ "title": this.plugin.nls.dialogTitle
+ }, this._dialogNode);
+ this._createDialogContent();
+ this._gotoPageDialog.startup();
+ },
+
+ _createDialogContent: function(){
+ // summary:
+ // Create the dialog content
+ this._specifyNode = dojo.create("div", {innerHTML: this.plugin.nls.dialogIndication}, this._gotoPageDialog.containerNode, "last");
+
+ this._pageInputDiv = dojo.create("div", {}, this._gotoPageDialog.containerNode, "last");
+ this._pageTextBox = new dijit.form.NumberTextBox();
+ this._pageTextBox.constraints = {fractional:false, min:1, max:this.pageCount};
+ this.plugin.connect(this._pageTextBox.textbox, "onkeyup", dojo.hitch(this, "_setConfirmBtnState"));
+
+ this._pageInputDiv.appendChild(this._pageTextBox.domNode);
+ this._pageLabel = dojo.create("label", {innerHTML: dojo.string.substitute(this.plugin.nls.pageCountIndication, [this.pageCount])}, this._pageInputDiv, "last");
+
+ this._buttonDiv = dojo.create("div", {}, this._gotoPageDialog.containerNode, "last");
+ this._confirmBtn = new dijit.form.Button({label: this.plugin.nls.dialogConfirm, onClick: dojo.hitch(this, this._onConfirm)});
+ this._confirmBtn.set("disabled", true);
+
+ this._cancelBtn = new dijit.form.Button({label: this.plugin.nls.dialogCancel, onClick: dojo.hitch(this, this._onCancel)});
+ this._buttonDiv.appendChild(this._confirmBtn.domNode);
+ this._buttonDiv.appendChild(this._cancelBtn.domNode);
+ this._styleContent();
+ this._gotoPageDialog.onCancel = dojo.hitch(this, this._onCancel);
+ this.plugin.connect(this._gotoPageDialog, "_onKey", dojo.hitch(this, "_onKeyDown"));
+ },
+
+ _styleContent: function(){
+ dojo.addClass(this._specifyNode, "dojoxGridDialogMargin");
+ dojo.addClass(this._pageInputDiv, "dojoxGridDialogMargin");
+ dojo.addClass(this._buttonDiv, "dojoxGridDialogButton");
+ dojo.style(this._pageTextBox.domNode, "width", "50px");
+ },
+
+ updatePageCount: function(){
+ this.pageCount = this.plugin.paginators[0]._getPageCount();
+ this._pageTextBox.constraints = {fractional:false, min:1, max:this.pageCount};
+ dojo.attr(this._pageLabel, "innerHTML", dojo.string.substitute(this.plugin.nls.pageCountIndication, [this.pageCount]));
+ },
+
+ showDialog: function(){
+ this._gotoPageDialog.show();
+ },
+
+ _onConfirm: function(event){
+ // summary:
+ // Jump to the given page
+ if(this._pageTextBox.isValid() && this._pageTextBox.getDisplayedValue() !== ""){
+ this.plugin.gotoPage(this._pageTextBox.getDisplayedValue());
+ this._gotoPageDialog.hide();
+ this._pageTextBox.reset();
+ }
+ this.plugin._stopEvent(event);
+ },
+
+ _onCancel: function(event){
+ // summary:
+ // Cancel action and hide the dialog
+ this._pageTextBox.reset();
+ this._gotoPageDialog.hide();
+ this.plugin._stopEvent(event);
+ },
+
+ _onKeyDown: function(event){
+ if(event.altKey || event.metaKey){
+ return;
+ }
+ var dk = dojo.keys;
+ if(event.keyCode === dk.ENTER){
+ this._onConfirm(event);
+ }
+ },
+
+ _setConfirmBtnState: function(){
+ if(this._pageTextBox.isValid() && this._pageTextBox.getDisplayedValue() !== ""){
+ this._confirmBtn.set("disabled", false);
+ }else{
+ this._confirmBtn.set("disabled", true);
+ }
+ },
+
+ destroy: function(){
+ this._pageTextBox.destroy();
+ this._confirmBtn.destroy();
+ this._cancelBtn.destroy();
+ this._gotoPageDialog.destroy();
+
+ dojo.destroy(this._specifyNode);
+ dojo.destroy(this._pageInputDiv);
+ dojo.destroy(this._pageLabel);
+ dojo.destroy(this._buttonDiv);
+ dojo.destroy(this._dialogNode);
+ }
+});
+
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Pagination/*name:'pagination'*/);
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Pagination.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Pagination.xd.js new file mode 100644 index 0000000..97a6497 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Pagination.xd.js @@ -0,0 +1,1245 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.Pagination"],
+["require", "dijit.form.NumberTextBox"],
+["require", "dijit.form.Button"],
+["require", "dojox.grid.enhanced._Plugin"],
+["require", "dojox.grid.enhanced.plugins.Dialog"],
+["require", "dojox.grid.enhanced.plugins._StoreLayer"],
+["requireLocalization", "dojox.grid.enhanced", "Pagination", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ru,sl,sv,th,tr,zh,zh-tw", "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ru,sl,sv,th,tr,zh,zh-tw"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.Pagination"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Pagination"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Pagination");
+
+dojo.require("dijit.form.NumberTextBox");
+dojo.require("dijit.form.Button");
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid.enhanced.plugins.Dialog");
+dojo.require("dojox.grid.enhanced.plugins._StoreLayer");
+
+;
+
+dojo.declare("dojox.grid.enhanced.plugins.Pagination", dojox.grid.enhanced._Plugin, {
+ // summary:
+ // The typical pagination way as an alternative to deal with huge data set besides the default virtual scrolling way
+
+ name: "pagination",
+ // The page size used with the store, default = 25.
+ pageSize: 25,
+
+ defaultRows: 25,
+
+ //current page we are at
+ _currentPage: 0,
+
+ //The currently obtained max # of rows to page through.
+ _maxSize: 0,
+
+ init: function(){
+ this.gh = null;
+ this.grid.rowsPerPage = this.pageSize = this.grid.rowsPerPage ? this.grid.rowsPerPage : this.pageSize;
+ this.grid.usingPagination = true;
+ this.nls = dojo.i18n.getLocalization("dojox.grid.enhanced", "Pagination");
+
+ this._wrapStoreLayer();
+ this._createPaginators(this.option);
+
+ this._regApis();
+ },
+
+ _createPaginators: function(paginationArgs){
+ // summary:
+ // Function to create the pagination control bar.
+ this.paginators = [];
+ if(paginationArgs.position === "both"){
+ this.paginators = [
+ new dojox.grid.enhanced.plugins._Paginator(dojo.mixin(paginationArgs, {position: "bottom", plugin: this})),
+ new dojox.grid.enhanced.plugins._Paginator(dojo.mixin(paginationArgs, {position: "top", plugin: this}))
+ ];
+ }else{
+ this.paginators = [new dojox.grid.enhanced.plugins._Paginator(dojo.mixin(paginationArgs, {plugin: this}))];
+ }
+ },
+
+ _wrapStoreLayer: function(){
+ var g = this.grid,
+ ns = dojox.grid.enhanced.plugins;
+ this._store = g.store;
+ this.query = g.query;
+
+ this.forcePageStoreLayer = new ns._ForcedPageStoreLayer(this);
+ ns.wrap(g, "_storeLayerFetch", this.forcePageStoreLayer);
+
+ this.connect(g, "setQuery", function(query){
+ if(query !== this.query){
+ this.query = query;
+ }
+ });
+ },
+
+ _stopEvent: function(event){
+ try{
+ dojo.stopEvent(event);
+ }catch(e){}
+ },
+
+ _onNew: function(item, parentInfo){
+ var totalPages = Math.ceil(this._maxSize / this.pageSize);
+ if(((this._currentPage + 1 === totalPages || totalPages === 0) && this.grid.rowCount < this.pageSize) || this.showAll){
+ dojo.hitch(this.grid, this._originalOnNew)(item, parentInfo);
+ this.forcePageStoreLayer.endIdx++;
+ }
+ this._maxSize++;
+ if(this.showAll){
+ this.pageSize++;
+ }
+ if(this.showAll && this.grid.autoHeight){
+ this.grid._refresh();
+ }else{
+ dojo.forEach(this.paginators, function(p){
+ p.update();
+ });
+ }
+ },
+
+ _removeSelectedRows: function(){
+ this._multiRemoving = true;
+ this._originalRemove();
+ this._multiRemoving = false;
+ this.grid.resize();
+ this.grid._refresh();
+ },
+
+ _onDelete: function(){
+ if(!this._multiRemoving){
+ this.grid.resize();
+ if(this.showAll){
+ this.grid._refresh();
+ }
+ }
+ if(this.grid.get('rowCount') === 0){
+ this.prevPage();
+ }
+ },
+
+ _regApis: function(){
+ // summary:
+ // register pagination public APIs to grid.
+ var g = this.grid;
+ // New added APIs
+ g.gotoPage = dojo.hitch(this, this.gotoPage);
+ g.nextPage = dojo.hitch(this, this.nextPage);
+ g.prevPage = dojo.hitch(this, this.prevPage);
+ g.gotoFirstPage = dojo.hitch(this, this.gotoFirstPage);
+ g.gotoLastPage = dojo.hitch(this, this.gotoLastPage);
+ g.changePageSize = dojo.hitch(this, this.changePageSize);
+ g.showGotoPageButton = dojo.hitch(this, this.showGotoPageButton);
+ g.getTotalRowCount = dojo.hitch(this, this.getTotalRowCount);
+ // Changed APIs
+ this.originalScrollToRow = dojo.hitch(g, g.scrollToRow);
+ g.scrollToRow = dojo.hitch(this, this.scrollToRow);
+ this._originalOnNew = dojo.hitch(g, g._onNew);
+ this._originalRemove = dojo.hitch(g, g.removeSelectedRows);
+ g.removeSelectedRows = dojo.hitch(this, this._removeSelectedRows);
+ g._onNew = dojo.hitch(this, this._onNew);
+ this.connect(g, "_onDelete", dojo.hitch(this, this._onDelete));
+ },
+
+ destroy: function(){
+ this.inherited(arguments);
+ var g = this.grid;
+ try{
+ dojo.forEach(this.paginators, function(p){
+ p.destroy();
+ });
+ g.unwrap(this.forcePageStoreLayer.name());
+ g._onNew = this._originalOnNew;
+ g.removeSelectedRows = this._originalRemove;
+ g.scrollToRow = this.originalScrollToRow;
+ this.paginators = null;
+ this.nls = null;
+ }catch(e){
+ console.warn("Pagination.destroy() error: ", e);
+ }
+ },
+
+ nextPage: function(){
+ // summary:
+ // Function to handle shifting to the next page in the list.
+ if(this._maxSize > ((this._currentPage + 1) * this.pageSize)){
+ //Current page is indexed at 0 and gotoPage expects 1-X. So to go
+ //up one, pass current page + 2!
+ this.gotoPage(this._currentPage + 2);
+ }
+ },
+
+ prevPage: function(){
+ // summary:
+ // Function to handle shifting to the previous page in the list.
+ if(this._currentPage > 0){
+ //Current page is indexed at 0 and gotoPage expects 1-X. So to go
+ //back one, pass current page!
+ this.gotoPage(this._currentPage);
+ }
+ },
+
+ gotoPage: function(page){
+ // summary:
+ // Function to handle shifting to an arbirtary page in the list.
+ // page:
+ // The page to go to, starting at 1.
+ var totalPages = Math.ceil(this._maxSize / this.pageSize);
+ page--;
+ if(page < totalPages && page >= 0 && this._currentPage !== page){
+ this._currentPage = page;
+ // this._updateSelected();
+ this.grid.setQuery(this.query);
+ this.grid.resize();
+ }
+ },
+
+ gotoFirstPage: function(){
+ // summary:
+ // Go to the first page
+ this.gotoPage(1);
+ },
+
+ gotoLastPage: function(){
+ // summary:
+ // Go to the last page
+ var totalPages = Math.ceil(this._maxSize / this.pageSize);
+ this.gotoPage(totalPages);
+ },
+
+ changePageSize: function(size){
+ // summary:
+ // Change size of items per page.
+ // This function will only be called by _Paginator
+ if(typeof size == "string"){
+ size = parseInt(size, 10);
+ }
+ var startIndex = this.pageSize * this._currentPage;
+ dojo.forEach(this.paginators, function(f){
+ f.currentPageSize = this.grid.rowsPerPage = this.pageSize = size;
+ if(size >= this._maxSize){
+ this.grid.rowsPerPage = this.defaultRows;
+ this.grid.usingPagination = false;
+ }else{
+ this.grid.usingPagination = true;
+ }
+ }, this);
+ var endIndex = startIndex + Math.min(this.pageSize, this._maxSize);
+ if(endIndex > this._maxSize){
+ this.gotoLastPage();
+ }else{
+ var cp = Math.ceil(startIndex / this.pageSize);
+ if(cp !== this._currentPage){
+ this.gotoPage(cp + 1);
+ }else{
+ this.grid._refresh(true);
+ }
+ }
+ this.grid.resize();
+ },
+
+ 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
+ dojo.forEach(this.paginators, function(p){
+ p._showGotoButton(flag);
+ });
+ },
+
+ 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.pageSize, 10),
+ totalPages = Math.ceil(this._maxSize / this.pageSize);
+ if(page > totalPages){
+ return;
+ }
+ this.gotoPage(page + 1);
+ var rowIdx = inRowIndex % this.pageSize;
+ this.grid.setScrollTop(this.grid.scroller.findScrollTop(rowIdx) + 1);
+ },
+
+ getTotalRowCount: function(){
+ // summary:
+ // Function for get total row count
+ return this._maxSize;
+ }
+});
+
+dojo.declare("dojox.grid.enhanced.plugins._ForcedPageStoreLayer", dojox.grid.enhanced.plugins._StoreLayer, {
+ tags: ["presentation"],
+
+ constructor: function(plugin){
+ this._plugin = plugin;
+ },
+
+ _fetch: function(request){
+ var self = this,
+ plugin = self._plugin,
+ grid = plugin.grid,
+ scope = request.scope || dojo.global,
+ onBegin = request.onBegin;
+
+ request.start = plugin._currentPage * plugin.pageSize + request.start;
+ self.startIdx = request.start;
+ self.endIdx = request.start + plugin.pageSize - 1;
+ if(onBegin && (plugin.showAll || dojo.every(plugin.paginators, function(p){
+ return plugin.showAll = !p.sizeSwitch && !p.pageStepper && !p.gotoButton;
+ }))){
+ request.onBegin = function(size, req){
+ plugin._maxSize = plugin.pageSize = size;
+ self.startIdx = 0;
+ self.endIdx = size - 1;
+ dojo.forEach(plugin.paginators, function(f){
+ f.update();
+ });
+ req.onBegin = onBegin;
+ req.onBegin.call(scope, size, req);
+ };
+ }else if(onBegin){
+ request.onBegin = function(size, req){
+ req.start = 0;
+ req.count = plugin.pageSize;
+ plugin._maxSize = size;
+ self.endIdx = self.endIdx > size ? (size - 1) : self.endIdx;
+ if(self.startIdx > size && size !== 0){
+ grid._pending_requests[req.start] = false;
+ plugin.gotoFirstPage();
+ }
+ dojo.forEach(plugin.paginators, function(f){
+ f.update();
+ });
+ req.onBegin = onBegin;
+ req.onBegin.call(scope, Math.min(plugin.pageSize, (size - self.startIdx)), req);
+ };
+ }
+ return dojo.hitch(this._store, this._originFetch)(request);
+ }
+});
+
+dojo.declare("dojox.grid.enhanced.plugins._Paginator", [dijit._Widget,dijit._Templated], {
+ templateString:"<div dojoAttachPoint=\"paginatorBar\">\r\n\t<table cellpadding=\"0\" cellspacing=\"0\" class=\"dojoxGridPaginator\">\r\n\t\t<tr>\r\n\t\t\t<td dojoAttachPoint=\"descriptionTd\" class=\"dojoxGridDescriptionTd\">\r\n\t\t\t\t<div dojoAttachPoint=\"descriptionDiv\" class=\"dojoxGridDescription\" />\r\n\t\t\t</td>\r\n\t\t\t<td dojoAttachPoint=\"sizeSwitchTd\"></td>\r\n\t\t\t<td dojoAttachPoint=\"pageStepperTd\" class=\"dojoxGridPaginatorFastStep\">\r\n\t\t\t\t<div dojoAttachPoint=\"pageStepperDiv\" class=\"dojoxGridPaginatorStep\"></div>\r\n\t\t\t</td>\r\n\t\t</tr>\r\n\t</table>\r\n</div>\r\n",
+
+ // pagination bar position - "bottom"|"top"
+ position: "bottom",
+
+ // max data item size
+ _maxItemSize: 0,
+
+ // description message status params
+ description: true,
+
+ // fast step page status params
+ pageStepper: true,
+
+ maxPageStep: 7,
+
+ // items per page size switch params
+ sizeSwitch: true,
+
+ pageSizes: ["10", "25", "50", "100", "All"],
+
+ gotoButton: false,
+
+ constructor: function(params){
+ dojo.mixin(this, params);
+ this.grid = this.plugin.grid;
+ this.itemTitle = this.itemTitle ? this.itemTitle : this.plugin.nls.itemTitle;
+ this.descTemplate = this.descTemplate ? this.descTemplate : this.plugin.nls.descTemplate;
+ },
+
+ postCreate: function(){
+ this.inherited(arguments);
+ this._setWidthValue();
+ var self = this;
+ var g = this.grid;
+ this.plugin.connect(g, "_resize", dojo.hitch(this, "_resetGridHeight"));
+ this._originalResize = dojo.hitch(g, "resize");
+ g.resize = function(changeSize, resultSize){
+ self._changeSize = g._pendingChangeSize = changeSize;
+ self._resultSize = g._pendingResultSize = resultSize;
+ g.sizeChange();
+ };
+ this._placeSelf();
+ },
+
+ destroy: function(){
+ this.inherited(arguments);
+ this.grid.focus.removeArea("pagination" + this.position.toLowerCase());
+ if(this._gotoPageDialog){
+ this._gotoPageDialog.destroy();
+ dojo.destroy(this.gotoPageTd);
+ delete this.gotoPageTd;
+ delete this._gotoPageDialog;
+ }
+ this.grid.resize = this._originalResize;
+ this.pageSizes = null;
+ },
+
+ update: function(){
+ // summary:
+ // Function to update paging information and update
+ // pagination bar display.
+ this.currentPageSize = this.plugin.pageSize;
+ this._maxItemSize = this.plugin._maxSize;
+
+ // update pagination bar display information
+ this._updateDescription();
+ this._updatePageStepper();
+ this._updateSizeSwitch();
+ this._updateGotoButton();
+ },
+
+ _setWidthValue: function(){
+ var type = ["description", "sizeSwitch", "pageStepper"];
+ var endWith = function(str1, str2){
+ var reg = new RegExp(str2+"$");
+ return reg.test(str1);
+ };
+ dojo.forEach(type, function(t){
+ var width, flag = this[t];
+ if(flag === undefined || typeof flag == "boolean"){
+ return;
+ }
+ if(dojo.isString(flag)){
+ width = endWith(flag, "px") || endWith(flag, "%") || endWith(flag, "em") ? flag : parseInt(flag, 10) > 0 ? parseInt(flag, 10) + "px" : null;
+ }else if(typeof flag === "number" && flag > 0){
+ width = flag + "px";
+ }
+ this[t] = width ? true : false;
+ this[t + "Width"] = width;
+ }, this);
+ },
+
+ _regFocusMgr: function(position){
+ // summary:
+ // Function to register pagination bar to focus manager.
+ this.grid.focus.addArea({
+ name: "pagination" + position,
+ onFocus: dojo.hitch(this, this._onFocusPaginator),
+ onBlur: dojo.hitch(this, this._onBlurPaginator),
+ onMove: dojo.hitch(this, this._moveFocus),
+ onKeyDown: dojo.hitch(this, this._onKeyDown)
+ });
+ switch(position){
+ case "top":
+ this.grid.focus.placeArea("pagination" + position, "before", "header");
+ break;
+ case "bottom":
+ default:
+ this.grid.focus.placeArea("pagination" + position, "after", "content");
+ break;
+ }
+ },
+
+ _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;
+ var position = dojo.trim(this.position.toLowerCase());
+ switch(position){
+ case "top":
+ this.placeAt(g.viewsHeaderNode, "before");
+ this._regFocusMgr("top");
+ break;
+ case "bottom":
+ default:
+ this.placeAt(g.viewsNode, "after");
+ this._regFocusMgr("bottom");
+ break;
+ }
+ },
+
+ _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 = dojo.contentBox(g.domNode).h + 2 * padBorder;
+ }
+ if(resultSize){
+ changeSize = resultSize;
+ }
+ if(changeSize){
+ this.plugin.gh = dojo.contentBox(g.domNode).h + 2 * padBorder;
+ }
+ var gh = this.plugin.gh,
+ hh = g._getHeaderHeight(),
+ ph = dojo.marginBox(this.domNode).h;
+ ph = this.plugin.paginators[1] ? ph * 2 : ph;
+ if(typeof g.autoHeight == "number"){
+ var cgh = gh + ph - padBorder;
+ dojo.style(g.domNode, "height", cgh + "px");
+ dojo.style(g.viewsNode, "height", (cgh - ph - hh) + "px");
+
+ this._styleMsgNode(hh, dojo.marginBox(g.viewsNode).w, cgh - ph - hh);
+ }else{
+ var h = gh - ph - hh - padBorder;
+ dojo.style(g.viewsNode, "height", h + "px");
+ var hasHScroller = dojo.some(g.views.views, function(v){
+ return v.hasHScrollbar();
+ });
+ dojo.forEach(g.viewsNode.childNodes, function(c, idx){
+ dojo.style(c, "height", h + "px");
+ });
+ dojo.forEach(g.views.views, function(v, idx){
+ if(v.scrollboxNode){
+ if(!v.hasHScrollbar() && hasHScroller){
+ dojo.style(v.scrollboxNode, "height", (h - dojox.html.metrics.getScrollbar().h) + "px");
+ }else{
+ dojo.style(v.scrollboxNode, "height", h + "px");
+ }
+ }
+ });
+ this._styleMsgNode(hh, dojo.marginBox(g.viewsNode).w, h);
+ }
+ },
+
+ _styleMsgNode: function(top, width, height){
+ var messagesNode = this.grid.messagesNode;
+ dojo.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;
+ if(this.description && this.descriptionDiv){
+ this.descriptionDiv.innerHTML = this._maxItemSize > 0 ? dojo.string.substitute(this.descTemplate, [this.itemTitle, this._maxItemSize, s.startIdx + 1, s.endIdx + 1]) : "0 " + this.itemTitle;
+ }
+ if(this.descriptionWidth){
+ dojo.style(this.descriptionTd, "width", this.descriptionWidth);
+ }
+ },
+
+ _updateSizeSwitch: function(){
+ // summary:
+ // Update "items per page" information.
+ if(!this.sizeSwitchTd){
+ return;
+ }
+ if(!this.sizeSwitch || this._maxItemSize <= 0){
+ dojo.style(this.sizeSwitchTd, "display", "none");
+ return;
+ }else{
+ dojo.style(this.sizeSwitchTd, "display", "");
+ }
+ if(this.initializedSizeNode && !this.pageSizeValue){
+ // do not update page size if page size was not changed
+ return;
+ }
+ if(this.sizeSwitchTd.childNodes.length < 1){
+ this._createSizeSwitchNodes();
+ }
+ this._updateSwitchNodeClass();
+
+ // move focus to next activable node
+ this._moveToNextActivableNode(this._getAllPageSizeNodes(), this.pageSizeValue);
+ this.pageSizeValue = null;
+ },
+
+ _createSizeSwitchNodes: function(){
+ // summary:
+ // The function to create the size switch nodes
+ var node = null;
+ if(!this.pageSizes || this.pageSizes.length < 1){
+ return;
+ }
+ dojo.forEach(this.pageSizes, function(size){
+ // create page size switch node
+ size = dojo.trim(size);
+ var labelValue = size.toLowerCase() == "all" ? this.plugin.nls.allItemsLabelTemplate : dojo.string.substitute(this.plugin.nls.pageSizeLabelTemplate, [size]);
+ node = dojo.create("span", {innerHTML: size, title: labelValue, value: size, tabindex: 0}, this.sizeSwitchTd, "last");
+ // for accessibility
+ dijit.setWaiState(node, "label", labelValue);
+ // connect event
+ this.plugin.connect(node, "onclick", dojo.hitch(this, "_onSwitchPageSize"));
+ this.plugin.connect(node, "onmouseover", function(e){
+ dojo.addClass(e.target, "dojoxGridPageTextHover");
+ });
+ this.plugin.connect(node, "onmouseout", function(e){
+ dojo.removeClass(e.target, "dojoxGridPageTextHover");
+ });
+ // create a separation node
+ node = dojo.create("span", {innerHTML: "|"}, this.sizeSwitchTd, "last");
+ dojo.addClass(node, "dojoxGridSeparator");
+ }, this);
+ // delete last separation node
+ dojo.destroy(node);
+ this.initializedSizeNode = true;
+ if(this.sizeSwitchWidth){
+ dojo.style(this.sizeSwitchTd, "width", this.sizeSwitchWidth);
+ }
+ },
+
+ _updateSwitchNodeClass: function(){
+ // summary:
+ // Update the switch nodes style
+ var size = null;
+ var hasActivedNode = false;
+ var styleNode = function(node, status){
+ if(status){
+ dojo.addClass(node, "dojoxGridActivedSwitch");
+ dojo.attr(node, "tabindex", "-1");
+ hasActivedNode = true;
+ }else{
+ dojo.addClass(node, "dojoxGridInactiveSwitch");
+ dojo.attr(node, "tabindex", "0");
+ }
+ };
+ dojo.forEach(this.sizeSwitchTd.childNodes, function(node){
+ if(node.value){
+ size = node.value;
+ dojo.removeClass(node);
+ if(this.pageSizeValue){
+ styleNode(node, size === this.pageSizeValue && !hasActivedNode);
+ }else{
+ if(size.toLowerCase() == "all"){
+ size = this._maxItemSize;
+ }
+ styleNode(node, this.currentPageSize === parseInt(size, 10) && !hasActivedNode);
+ }
+ }
+ }, this);
+ },
+
+ _updatePageStepper: function(){
+ // summary:
+ // Update the page step nodes
+ if(!this.pageStepperTd){
+ return;
+ }
+ if(!this.pageStepper || this._maxItemSize <= 0){
+ dojo.style(this.pageStepperTd, "display", "none");
+ return;
+ }else{
+ dojo.style(this.pageStepperTd, "display", "");
+ }
+ if(this.pageStepperDiv.childNodes.length < 1){
+ this._createPageStepNodes();
+ this._createWardBtns();
+ }else{
+ this._resetPageStepNodes();
+ }
+ this._updatePageStepNodeClass();
+
+ this._moveToNextActivableNode(this._getAllPageStepNodes(), this.pageStepValue);
+ this.pageStepValue = null;
+ },
+
+ _createPageStepNodes: function(){
+ // summary:
+ // Create the page step nodes if they do not exist
+ var startPage = this._getStartPage(),
+ stepSize = this._getStepPageSize(),
+ label = "",
+ node = null;
+ for(var i = startPage; i < this.maxPageStep + 1; i++){
+ label = dojo.string.substitute(this.plugin.nls.pageStepLabelTemplate, [i + ""]);
+ node = dojo.create("div", {innerHTML: i, value: i, title: label, tabindex: i < startPage + stepSize ? 0 : -1}, this.pageStepperDiv, "last");
+ dijit.setWaiState(node, "label", label);
+ // connect event
+ this.plugin.connect(node, "onclick", dojo.hitch(this, "_onPageStep"));
+ this.plugin.connect(node, "onmouseover", function(e){
+ dojo.addClass(e.target, "dojoxGridPageTextHover");
+ });
+ this.plugin.connect(node, "onmouseout", function(e){
+ dojo.removeClass(e.target, "dojoxGridPageTextHover");
+ });
+ dojo.style(node, "display", i < startPage + stepSize ? "block" : "none");
+ }
+ if(this.pageStepperWidth){
+ dojo.style(this.pageStepperTd, "width", this.pageStepperWidth);
+ }
+ },
+
+ _createWardBtns: function(){
+ // summary:
+ // Create the previous/next/first/last button
+ var self = this;
+ var highContrastLabel = {prevPage: "<", firstPage: "«", nextPage: ">", lastPage: "»"};
+ var createWardBtn = function(value, label, position){
+ var node = dojo.create("div", {value: value, title: label, tabindex: 1}, self.pageStepperDiv, position);
+ self.plugin.connect(node, "onclick", dojo.hitch(self, "_onPageStep"));
+ dijit.setWaiState(node, "label", label);
+ // for high contrast
+ var highConrastNode = dojo.create("span", {value: value, title: label, innerHTML: highContrastLabel[value]}, node, position);
+ dojo.addClass(highConrastNode, "dojoxGridWardButtonInner");
+ };
+ createWardBtn("prevPage", this.plugin.nls.prevTip, "first");
+ createWardBtn("firstPage", this.plugin.nls.firstTip, "first");
+ createWardBtn("nextPage", this.plugin.nls.nextTip, "last");
+ createWardBtn("lastPage", this.plugin.nls.lastTip, "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;
+ for(var i = startPage, j = 2; j < stepNodes.length - 2; j++, i++){
+ node = stepNodes[j];
+ if(i < startPage + stepSize){
+ dojo.attr(node, "innerHTML", i);
+ dojo.attr(node, "value", i);
+ dojo.style(node, "display", "block");
+ dijit.setWaiState(node, "label", dojo.string.substitute(this.plugin.nls.pageStepLabelTemplate, [i + ""]));
+ }else{
+ dojo.style(node, "display", "none");
+ }
+ }
+ },
+
+ _updatePageStepNodeClass: function(){
+ // summary:
+ // Update the style of the page step nodes
+ var value = null,
+ curPage = this._getCurrentPageNo(),
+ pageCount = this._getPageCount(),
+ visibleNodeLen = 0;
+
+ var updateClass = function(node, isWardBtn, status){
+ var value = node.value,
+ enableClass = isWardBtn ? "dojoxGrid" + value + "Btn" : "dojoxGridInactived",
+ disableClass = isWardBtn ? "dojoxGrid" + value + "BtnDisable" : "dojoxGridActived";
+ if(status){
+ dojo.addClass(node, disableClass);
+ dojo.attr(node, "tabindex", "-1");
+ }else{
+ dojo.addClass(node, enableClass);
+ dojo.attr(node, "tabindex", "0");
+ }
+ };
+ dojo.forEach(this.pageStepperDiv.childNodes, function(node){
+ dojo.removeClass(node);
+ if(isNaN(parseInt(node.value, 10))){
+ dojo.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 || dojo.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.gotoPageTd){
+ if(this._gotoPageDialog){
+ this._gotoPageDialog.destroy();
+ }
+ dojo.destroy(this.gotoPageDiv);
+ dojo.destroy(this.gotoPageTd);
+ delete this.gotoPageDiv;
+ delete this.gotoPageTd;
+ }
+ return;
+ }
+ if(!this.gotoPageTd){
+ this._createGotoNode();
+ }
+ dojo.toggleClass(this.gotoPageDiv, "dojoxGridPaginatorGotoDivDisabled", this.plugin.pageSize >= this.plugin._maxSize);
+ },
+
+ _createGotoNode: function(){
+ // summary:
+ // Create the goto page button
+ this.gotoPageTd = dojo.create("td", {}, dojo.query("tr", this.domNode)[0], "last");
+ dojo.addClass(this.gotoPageTd, "dojoxGridPaginatorGotoTd");
+ this.gotoPageDiv = dojo.create("div", {tabindex: "0", title: this.plugin.nls.gotoButtonTitle}, this.gotoPageTd, "first");
+ dojo.addClass(this.gotoPageDiv, "dojoxGridPaginatorGotoDiv");
+ this.plugin.connect(this.gotoPageDiv, "onclick", dojo.hitch(this, "_openGotopageDialog"));
+ // for high contrast
+ var highConrastNode = dojo.create("span", {title: this.plugin.nls.gotoButtonTitle, innerHTML: "⊥"}, this.gotoPageDiv, "last");
+ dojo.addClass(highConrastNode, "dojoxGridWardButtonInner");
+ },
+
+ _openGotopageDialog: function(event){
+ // summary:
+ // Show the goto page dialog
+ if(!this._gotoPageDialog){
+ this._gotoPageDialog = new dojox.grid.enhanced.plugins.pagination._GotoPageDialog(this.plugin);
+ }
+ // focus
+ if(!this._currentFocusNode){
+ this.grid.focus.focusArea("pagination" + this.position, event);
+ }else{
+ this._currentFocusNode = this.gotoPageDiv;
+ }
+ if(this.focusArea != "pageStep"){
+ this.focusArea = "pageStep";
+ }
+ this._gotoPageDialog.updatePageCount();
+ this._gotoPageDialog.showDialog();
+ },
+
+ // ===== focus handlers ===== //
+ _onFocusPaginator: function(event, step){
+ // summary:
+ // Focus handler
+ if(!this._currentFocusNode){
+ if(step > 0){
+ return this._onFocusPageSizeNode(event) ? true : this._onFocusPageStepNode(event);
+ }else if(step < 0){
+ return this._onFocusPageStepNode(event) ? true : this._onFocusPageSizeNode(event);
+ }else{
+ return false;
+ }
+ }else{
+ if(step > 0){
+ return this.focusArea === "pageSize" ? this._onFocusPageStepNode(event) : false;
+ }else if(step < 0){
+ return this.focusArea === "pageStep" ? this._onFocusPageSizeNode(event) : false;
+ }else{
+ return false;
+ }
+ }
+ },
+
+ _onFocusPageSizeNode: function(event){
+ // summary:
+ // Focus the page size area, if there is no focusable node, return false
+ var pageSizeNodes = this._getPageSizeActivableNodes();
+ if(event && event.type !== "click"){
+ if(pageSizeNodes[0]){
+ dijit.focus(pageSizeNodes[0]);
+ this._currentFocusNode = pageSizeNodes[0];
+ this.focusArea = "pageSize";
+ this.plugin._stopEvent(event);
+ return true;
+ }else{
+ return false;
+ }
+ }
+ if(event && event.type == "click"){
+ if(dojo.indexOf(this._getPageSizeActivableNodes(), event.target) > -1){
+ this.focusArea = "pageSize";
+ this.plugin._stopEvent(event);
+ return true;
+ }
+ }
+ return false;
+ },
+
+ _onFocusPageStepNode: function(event){
+ // summary:
+ // Focus the page step area, if there is no focusable node, return false
+ var pageStepNodes = this._getPageStepActivableNodes();
+ if(event && event.type !== "click"){
+ if(pageStepNodes[0]){
+ dijit.focus(pageStepNodes[0]);
+ this._currentFocusNode = pageStepNodes[0];
+ this.focusArea = "pageStep";
+ this.plugin._stopEvent(event);
+ return true;
+ }else if(this.gotoPageDiv){
+ dijit.focus(this.gotoPageDiv);
+ this._currentFocusNode = this.gotoPageDiv;
+ this.focusArea = "pageStep";
+ this.plugin._stopEvent(event);
+ return true;
+ }else{
+ return false;
+ }
+ }
+ if(event && event.type == "click"){
+ if(dojo.indexOf(this._getPageStepActivableNodes(), event.target) > -1){
+ this.focusArea = "pageStep";
+ this.plugin._stopEvent(event);
+ return true;
+ }else if(event.target == this.gotoPageDiv){
+ dijit.focus(this.gotoPageDiv);
+ this._currentFocusNode = this.gotoPageDiv;
+ this.focusArea = "pageStep";
+ this.plugin._stopEvent(event);
+ return true;
+ }
+ }
+ return false;
+ },
+
+ _onFocusGotoPageNode: function(event){
+ // summary:
+ // Focus the goto page button, if there is no focusable node, return false
+ if(!this.gotoButton || !this.gotoPageTd){
+ return false;
+ }
+ if(event && event.type !== "click" || (event.type == "click" && event.target == this.gotoPageDiv)){
+ dijit.focus(this.gotoPageDiv);
+ this._currentFocusNode = this.gotoPageDiv;
+ this.focusArea = "gotoButton";
+ this.plugin._stopEvent(event);
+ return true;
+ }
+ return true;
+ },
+
+ _onBlurPaginator: function(event, step){
+ var pageSizeNodes = this._getPageSizeActivableNodes(),
+ pageStepNodes = this._getPageStepActivableNodes();
+
+ if(step > 0 && this.focusArea === "pageSize" && (pageStepNodes.length > 1 || this.gotoButton)){
+ return false;
+ }else if(step < 0 && this.focusArea === "pageStep" && pageSizeNodes.length > 1){
+ return false;
+ }
+ this._currentFocusNode = null;
+ this.focusArea = null;
+ return true;
+ },
+
+ _onKeyDown: function(event, isBubble){
+ // summary:
+ // Focus navigation
+ if(isBubble){
+ return;
+ }
+ if(event.altKey || event.metaKey){
+ return;
+ }
+ var dk = dojo.keys;
+ if(event.keyCode === dk.ENTER || event.keyCode === dk.SPACE){
+ if(dojo.indexOf(this._getPageStepActivableNodes(), this._currentFocusNode) > -1){
+ this._onPageStep(event);
+ }else if(dojo.indexOf(this._getPageSizeActivableNodes(), this._currentFocusNode) > -1){
+ this._onSwitchPageSize(event);
+ }else if(this._currentFocusNode === this.gotoPageDiv){
+ this._openGotopageDialog(event);
+ }
+ }
+ this.plugin._stopEvent(event);
+ },
+
+ _moveFocus: function(rowDelta, colDelta, evt){
+ // summary:
+ // Move focus according row delta&column delta
+ var nodes;
+ if(this.focusArea == "pageSize"){
+ nodes = this._getPageSizeActivableNodes();
+ }else if(this.focusArea == "pageStep"){
+ nodes = this._getPageStepActivableNodes();
+ if(this.gotoPageDiv){
+ nodes.push(this.gotoPageDiv);
+ }
+ }
+ if(nodes.length < 1){
+ return;
+ }
+ var currentIdx = dojo.indexOf(nodes, this._currentFocusNode);
+ var focusIdx = currentIdx + colDelta;
+ if(focusIdx >= 0 && focusIdx < nodes.length){
+ dijit.focus(nodes[focusIdx]);
+ this._currentFocusNode = nodes[focusIdx];
+ }
+ this.plugin._stopEvent(evt);
+ },
+
+ _getPageSizeActivableNodes: function(){
+ return dojo.query("span[tabindex='0']", this.sizeSwitchTd);
+ },
+
+ _getPageStepActivableNodes: function(){
+ return (dojo.query("div[tabindex='0']", this.pageStepperDiv));
+ },
+
+ _getAllPageSizeNodes: function(){
+ var nodeList = [];
+ dojo.forEach(this.sizeSwitchTd.childNodes, function(node){
+ if(node.value){
+ nodeList.push(node);
+ }
+ });
+ return nodeList;
+ },
+
+ _getAllPageStepNodes: function(){
+ var nodeList = [];
+ for(var i = 0, len = this.pageStepperDiv.childNodes.length; i < len; i++){
+ nodeList.push(this.pageStepperDiv.childNodes[i]);
+ }
+ return nodeList;
+ },
+
+ _moveToNextActivableNode: function(nodeList, curNodeValue){
+ // summary:
+ // Need to move the focus to next node since current node is inactive and unfocusable
+ if(!curNodeValue){
+ return;
+ }
+ if(nodeList.length < 2){
+ this.grid.focus.tab(1);
+ }
+ var nl = [],
+ node = null,
+ index = 0;
+ dojo.forEach(nodeList, function(n){
+ if(n.value == curNodeValue){
+ nl.push(n);
+ node = n;
+ }else if(dojo.attr(n, "tabindex") == "0"){
+ nl.push(n);
+ }
+ });
+ if(nl.length < 2){
+ this.grid.focus.tab(1);
+ }
+ index = dojo.indexOf(nl, node);
+ if(dojo.attr(node, "tabindex") != "0"){
+ node = nl[index + 1] ? nl[index + 1] : nl[index - 1];
+ }
+ dijit.focus(node);
+ this._currentFocusNode = node;
+ },
+
+ // ===== pagination events handlers ===== //
+ _onSwitchPageSize: function(/*Event*/e){
+ // summary:
+ // The handler of switch the page size
+ var size = this.pageSizeValue = e.target.value;
+ if(!size){
+ return;
+ }
+ if(dojo.trim(size.toLowerCase()) == "all"){
+ size = this._maxItemSize;
+ }
+ this.plugin.showAll = parseInt(size, 10) >= this._maxItemSize ? true : false;
+ this.plugin.grid.usingPagination = !this.plugin.showAll;
+
+ size = parseInt(size, 10);
+ if(isNaN(size) || size <= 0/* || size == this.currentPageSize*/){
+ return;
+ }
+
+ if(!this._currentFocusNode){
+ this.grid.focus.currentArea("pagination" + this.position);
+ }
+ if(this.focusArea != "pageSize"){
+ this.focusArea = "pageSize";
+ }
+ this.plugin.changePageSize(size);
+ },
+
+ _onPageStep: function(/*Event*/e){
+ // summary:
+ // The handler jump page event
+ var p = this.plugin,
+ value = this.pageStepValue = e.target.value;
+
+ if(!this._currentFocusNode){
+ this.grid.focus.currentArea("pagination" + this.position);
+ }
+ if(this.focusArea != "pageStep"){
+ this.focusArea = "pageStep";
+ }
+ if(!isNaN(parseInt(value, 10))){
+ p.gotoPage(value);
+ }else{
+ switch(e.target.value){
+ case "prevPage":
+ p.prevPage();
+ break;
+ case "nextPage":
+ p.nextPage();
+ break;
+ case "firstPage":
+ p.gotoFirstPage();
+ break;
+ case "lastPage":
+ p.gotoLastPage();
+ }
+ }
+ },
+
+ // ===== information getters ===== //
+ _getCurrentPageNo: function(){
+ return this.plugin._currentPage + 1;
+ },
+
+ _getPageCount: function(){
+ if(!this._maxItemSize || !this.currentPageSize){
+ return 0;
+ }
+ return Math.ceil(this._maxItemSize / this.currentPageSize);
+ },
+
+ _getStartPage: function(){
+ var cp = this._getCurrentPageNo();
+ var ms = parseInt(this.maxPageStep / 2, 10);
+ var pc = this._getPageCount();
+ if(cp < ms || (cp - ms) < 1){
+ return 1;
+ }else if(pc <= this.maxPageStep){
+ return 1;
+ }else{
+ if(pc - cp < ms && cp - this.maxPageStep >= 0){
+ return pc - this.maxPageStep + 1;
+ }else{
+ return (cp - ms);
+ }
+ }
+ },
+
+ _getStepPageSize: function(){
+ var sp = this._getStartPage();
+ var count = this._getPageCount();
+ if((sp + this.maxPageStep) > count){
+ return count - sp + 1;
+ }else{
+ return this.maxPageStep;
+ }
+ }
+
+});
+
+dojo.declare("dojox.grid.enhanced.plugins.pagination._GotoPageDialog", null, {
+
+ pageCount: 0,
+
+ constructor: function(plugin){
+ this.plugin = plugin;
+ this.pageCount = this.plugin.paginators[0]._getPageCount();
+ this._dialogNode = dojo.create("div", {}, dojo.body(), "last");
+ this._gotoPageDialog = new dojox.grid.enhanced.plugins.Dialog({
+ "refNode": plugin.grid.domNode,
+ "title": this.plugin.nls.dialogTitle
+ }, this._dialogNode);
+ this._createDialogContent();
+ this._gotoPageDialog.startup();
+ },
+
+ _createDialogContent: function(){
+ // summary:
+ // Create the dialog content
+ this._specifyNode = dojo.create("div", {innerHTML: this.plugin.nls.dialogIndication}, this._gotoPageDialog.containerNode, "last");
+
+ this._pageInputDiv = dojo.create("div", {}, this._gotoPageDialog.containerNode, "last");
+ this._pageTextBox = new dijit.form.NumberTextBox();
+ this._pageTextBox.constraints = {fractional:false, min:1, max:this.pageCount};
+ this.plugin.connect(this._pageTextBox.textbox, "onkeyup", dojo.hitch(this, "_setConfirmBtnState"));
+
+ this._pageInputDiv.appendChild(this._pageTextBox.domNode);
+ this._pageLabel = dojo.create("label", {innerHTML: dojo.string.substitute(this.plugin.nls.pageCountIndication, [this.pageCount])}, this._pageInputDiv, "last");
+
+ this._buttonDiv = dojo.create("div", {}, this._gotoPageDialog.containerNode, "last");
+ this._confirmBtn = new dijit.form.Button({label: this.plugin.nls.dialogConfirm, onClick: dojo.hitch(this, this._onConfirm)});
+ this._confirmBtn.set("disabled", true);
+
+ this._cancelBtn = new dijit.form.Button({label: this.plugin.nls.dialogCancel, onClick: dojo.hitch(this, this._onCancel)});
+ this._buttonDiv.appendChild(this._confirmBtn.domNode);
+ this._buttonDiv.appendChild(this._cancelBtn.domNode);
+ this._styleContent();
+ this._gotoPageDialog.onCancel = dojo.hitch(this, this._onCancel);
+ this.plugin.connect(this._gotoPageDialog, "_onKey", dojo.hitch(this, "_onKeyDown"));
+ },
+
+ _styleContent: function(){
+ dojo.addClass(this._specifyNode, "dojoxGridDialogMargin");
+ dojo.addClass(this._pageInputDiv, "dojoxGridDialogMargin");
+ dojo.addClass(this._buttonDiv, "dojoxGridDialogButton");
+ dojo.style(this._pageTextBox.domNode, "width", "50px");
+ },
+
+ updatePageCount: function(){
+ this.pageCount = this.plugin.paginators[0]._getPageCount();
+ this._pageTextBox.constraints = {fractional:false, min:1, max:this.pageCount};
+ dojo.attr(this._pageLabel, "innerHTML", dojo.string.substitute(this.plugin.nls.pageCountIndication, [this.pageCount]));
+ },
+
+ showDialog: function(){
+ this._gotoPageDialog.show();
+ },
+
+ _onConfirm: function(event){
+ // summary:
+ // Jump to the given page
+ if(this._pageTextBox.isValid() && this._pageTextBox.getDisplayedValue() !== ""){
+ this.plugin.gotoPage(this._pageTextBox.getDisplayedValue());
+ this._gotoPageDialog.hide();
+ this._pageTextBox.reset();
+ }
+ this.plugin._stopEvent(event);
+ },
+
+ _onCancel: function(event){
+ // summary:
+ // Cancel action and hide the dialog
+ this._pageTextBox.reset();
+ this._gotoPageDialog.hide();
+ this.plugin._stopEvent(event);
+ },
+
+ _onKeyDown: function(event){
+ if(event.altKey || event.metaKey){
+ return;
+ }
+ var dk = dojo.keys;
+ if(event.keyCode === dk.ENTER){
+ this._onConfirm(event);
+ }
+ },
+
+ _setConfirmBtnState: function(){
+ if(this._pageTextBox.isValid() && this._pageTextBox.getDisplayedValue() !== ""){
+ this._confirmBtn.set("disabled", false);
+ }else{
+ this._confirmBtn.set("disabled", true);
+ }
+ },
+
+ destroy: function(){
+ this._pageTextBox.destroy();
+ this._confirmBtn.destroy();
+ this._cancelBtn.destroy();
+ this._gotoPageDialog.destroy();
+
+ dojo.destroy(this._specifyNode);
+ dojo.destroy(this._pageInputDiv);
+ dojo.destroy(this._pageLabel);
+ dojo.destroy(this._buttonDiv);
+ dojo.destroy(this._dialogNode);
+ }
+});
+
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Pagination/*name:'pagination'*/);
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Printer.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Printer.js new file mode 100644 index 0000000..a8b55cc --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Printer.js @@ -0,0 +1,269 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.Printer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Printer"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Printer");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid.enhanced.plugins.exporter.TableWriter");
+
+dojo.declare("dojox.grid.enhanced.plugins.Printer", dojox.grid.enhanced._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 = dojo.hitch(this, this.printGrid);
+ g.printSelected = dojo.hitch(this, this.printSelected);
+ g.exportToHTML = dojo.hitch(this, this.exportToHTML);
+ g.exportSelectedToHTML = dojo.hitch(this, this.exportSelectedToHTML);
+ g.normalizePrintedGrid = dojo.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, dojo.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._print(this.exportSelectedToHTML(args));
+ },
+ 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){
+ onExported(_this._wrapHTML(args.title, args.cssFiles, args.titleInBody + str));
+ });
+ },
+ exportSelectedToHTML: function(args){
+ // 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 str = this.grid.exportSelected("table", args.writerArgs);
+ return this._wrapHTML(args.title, args.cssFiles, args.titleInBody + str); //String
+ },
+ _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 = win.document;
+ doc.open();
+ doc.write(htmlStr);
+ doc.close();
+ _this.normalizeRowHeight(doc);
+ };
+ if(!window.print){
+ //We don't have a print facility.
+ return;
+ }else if(dojo.isChrome || dojo.isOpera){
+ //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);
+ //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.print();
+ 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 = dojo.byId(frameId))){
+ //create an iframe to store the grid data.
+ fn = dojo.create("iframe");
+ fn.id = frameId;
+ fn.frameBorder = 0;
+ dojo.style(fn, {
+ width: "1px",
+ height: "1px",
+ position: "absolute",
+ right: 0,
+ bottoom: 0,
+ border: "none",
+ overflow: "hidden"
+ });
+ if(!dojo.isIE){
+ dojo.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, but since this is okay for all
+ // no special casing.
+ dijit.focus(fn);
+ 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
+ var html = ['<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
+ '<html><head><title>', title,
+ '</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>'];
+ for(var i = 0; i < cssFiles.length; ++i){
+ html.push('<link rel="stylesheet" type="text/css" href="' + cssFiles[i] + '" />');
+ }
+ html.push('</head>');
+ if(body_content.search(/^\s*<body/i) < 0){
+ body_content = '<body>' + body_content + '</body>';
+ }
+ html.push(body_content);
+ return html.join('\n'); //String
+ },
+ normalizeRowHeight: function(doc){
+ var views = dojo.query("table.grid_view", doc.body);
+ var headPerView = dojo.map(views, function(view){
+ return dojo.query("thead.grid_header", view)[0];
+ });
+ var rowsPerView = dojo.map(views, function(view){
+ return dojo.query("tbody.grid_row", view);
+ });
+ var rowCount = rowsPerView[0].length;
+ var i, v, h, maxHeight = 0;
+ for(v = views.length - 1; v >= 0; --v){
+ h = dojo.contentBox(headPerView[v]).h;
+ if(h > maxHeight){
+ maxHeight = h;
+ }
+ }
+ for(v = views.length - 1; v >= 0; --v){
+ dojo.style(headPerView[v], "height", maxHeight + "px");
+ }
+ for(i = 0; i < rowCount; ++i){
+ maxHeight = 0;
+ for(v = views.length - 1; v >= 0; --v){
+ h = dojo.contentBox(rowsPerView[v][i]).h;
+ if(h > maxHeight){
+ maxHeight = h;
+ }
+ }
+ for(v = views.length - 1; v >= 0; --v){
+ dojo.style(rowsPerView[v][i], "height", maxHeight + "px");
+ }
+ }
+ var left = 0;
+ for(v = 0; v < views.length; ++v){
+ dojo.style(views[v], "left", left + "px");
+ left += dojo.marginBox(views[v]).w;
+ }
+ },
+ _formalizeArgs: function(args){
+ args = (args && dojo.isObject(args)) ? args : {};
+ args.title = String(args.title) || "";
+ if(!dojo.isArray(args.cssFiles)){
+ args.cssFiles = [args.cssFiles];
+ }
+ args.titleInBody = args.title ? ['<h1>', args.title, '</h1>'].join('') : '';
+ return args; //Object
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Printer/*name:'printer'*/, {
+ "dependency": ["exporter"]
+});
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Printer.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Printer.xd.js new file mode 100644 index 0000000..a2b4bd3 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Printer.xd.js @@ -0,0 +1,275 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.Printer"],
+["require", "dojox.grid.enhanced._Plugin"],
+["require", "dojox.grid.enhanced.plugins.exporter.TableWriter"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.Printer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Printer"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Printer");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid.enhanced.plugins.exporter.TableWriter");
+
+dojo.declare("dojox.grid.enhanced.plugins.Printer", dojox.grid.enhanced._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 = dojo.hitch(this, this.printGrid);
+ g.printSelected = dojo.hitch(this, this.printSelected);
+ g.exportToHTML = dojo.hitch(this, this.exportToHTML);
+ g.exportSelectedToHTML = dojo.hitch(this, this.exportSelectedToHTML);
+ g.normalizePrintedGrid = dojo.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, dojo.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._print(this.exportSelectedToHTML(args));
+ },
+ 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){
+ onExported(_this._wrapHTML(args.title, args.cssFiles, args.titleInBody + str));
+ });
+ },
+ exportSelectedToHTML: function(args){
+ // 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 str = this.grid.exportSelected("table", args.writerArgs);
+ return this._wrapHTML(args.title, args.cssFiles, args.titleInBody + str); //String
+ },
+ _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 = win.document;
+ doc.open();
+ doc.write(htmlStr);
+ doc.close();
+ _this.normalizeRowHeight(doc);
+ };
+ if(!window.print){
+ //We don't have a print facility.
+ return;
+ }else if(dojo.isChrome || dojo.isOpera){
+ //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);
+ //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.print();
+ 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 = dojo.byId(frameId))){
+ //create an iframe to store the grid data.
+ fn = dojo.create("iframe");
+ fn.id = frameId;
+ fn.frameBorder = 0;
+ dojo.style(fn, {
+ width: "1px",
+ height: "1px",
+ position: "absolute",
+ right: 0,
+ bottoom: 0,
+ border: "none",
+ overflow: "hidden"
+ });
+ if(!dojo.isIE){
+ dojo.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, but since this is okay for all
+ // no special casing.
+ dijit.focus(fn);
+ 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
+ var html = ['<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
+ '<html><head><title>', title,
+ '</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>'];
+ for(var i = 0; i < cssFiles.length; ++i){
+ html.push('<link rel="stylesheet" type="text/css" href="' + cssFiles[i] + '" />');
+ }
+ html.push('</head>');
+ if(body_content.search(/^\s*<body/i) < 0){
+ body_content = '<body>' + body_content + '</body>';
+ }
+ html.push(body_content);
+ return html.join('\n'); //String
+ },
+ normalizeRowHeight: function(doc){
+ var views = dojo.query("table.grid_view", doc.body);
+ var headPerView = dojo.map(views, function(view){
+ return dojo.query("thead.grid_header", view)[0];
+ });
+ var rowsPerView = dojo.map(views, function(view){
+ return dojo.query("tbody.grid_row", view);
+ });
+ var rowCount = rowsPerView[0].length;
+ var i, v, h, maxHeight = 0;
+ for(v = views.length - 1; v >= 0; --v){
+ h = dojo.contentBox(headPerView[v]).h;
+ if(h > maxHeight){
+ maxHeight = h;
+ }
+ }
+ for(v = views.length - 1; v >= 0; --v){
+ dojo.style(headPerView[v], "height", maxHeight + "px");
+ }
+ for(i = 0; i < rowCount; ++i){
+ maxHeight = 0;
+ for(v = views.length - 1; v >= 0; --v){
+ h = dojo.contentBox(rowsPerView[v][i]).h;
+ if(h > maxHeight){
+ maxHeight = h;
+ }
+ }
+ for(v = views.length - 1; v >= 0; --v){
+ dojo.style(rowsPerView[v][i], "height", maxHeight + "px");
+ }
+ }
+ var left = 0;
+ for(v = 0; v < views.length; ++v){
+ dojo.style(views[v], "left", left + "px");
+ left += dojo.marginBox(views[v]).w;
+ }
+ },
+ _formalizeArgs: function(args){
+ args = (args && dojo.isObject(args)) ? args : {};
+ args.title = String(args.title) || "";
+ if(!dojo.isArray(args.cssFiles)){
+ args.cssFiles = [args.cssFiles];
+ }
+ args.titleInBody = args.title ? ['<h1>', args.title, '</h1>'].join('') : '';
+ return args; //Object
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Printer/*name:'printer'*/, {
+ "dependency": ["exporter"]
+});
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Rearrange.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Rearrange.js new file mode 100644 index 0000000..1d1584a --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Rearrange.js @@ -0,0 +1,492 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.Rearrange"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Rearrange"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Rearrange");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid.enhanced.plugins._RowMapLayer");
+
+dojo.declare("dojox.grid.enhanced.plugins.Rearrange", dojox.grid.enhanced._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 dojox.grid.enhanced.plugins._RowMapLayer(grid);
+ dojox.grid.enhanced.plugins.wrap(grid, "_storeLayerFetch", rowMapLayer);
+ },
+ setArgs: function(args){
+ this.args = dojo.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(dojo.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;
+ var rightCount = 0;
+ var maxCol = Math.max(colsToMove[colsToMove.length - 1], targetPos);
+ if(maxCol == cells.length){
+ --maxCol;
+ }
+ for(i = colsToMove[0]; i <= maxCol; ++i){
+ var j = tmp[i];
+ if(j >= 0){
+ if(i != targetPos - delta + j){
+ mapping[i] = targetPos - delta + j;
+ }
+ leftCount = j + 1;
+ rightCount = colsToMove.length - j - 1;
+ }else if(i < targetPos && leftCount > 0){
+ mapping[i] = i - leftCount;
+ }else if(i >= targetPos && rightCount > 0){
+ mapping[i] = i + 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;
+ dojo.publish("dojox/grid/rearrange/move/" + g.id, ["col", mapping]);
+ },
+ 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 = {};
+ dojo.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 = {};
+ dojo.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 = dojo.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(){
+ dojo.publish("dojox/grid/rearrange/move/" + g.id, ["row", tmpMapping]);
+ 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;
+ }
+ dojo.forEach(sources, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, "");
+ });
+ dojo.forEach(targets, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, point.v);
+ });
+ s.save({
+ onComplete: function(){
+ dojo.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;
+ }
+ dojo.forEach(targets, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, point.v);
+ });
+ s.save({
+ onComplete: function(){
+ setTimeout(function(){
+ dojo.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;
+ }
+ dojo.forEach(targets, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, point.v);
+ });
+ s.save({
+ onComplete: function(){
+ dojo.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;
+ }
+ dojo.forEach(targets, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, "");
+ });
+ s.save({
+ onComplete: function(){
+ dojo.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,
+ _this = this;
+ var len = rowsToMove.length;
+ 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;
+ for(i = 0; !thisItem; ++i){
+ thisItem = g._by_idx[i];
+ }
+ var attrs = s.getAttributes(thisItem.item);
+ var rowsToFetch = [];
+ dojo.forEach(rowsToMove, function(rowIndex, i){
+ var item = {};
+ var srcItem = srcg._by_idx[rowIndex];
+ if(srcItem){
+ dojo.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 && dojo.isObject(rowsToMove[0])){
+ dojo.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(){
+ dojo.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{
+ dojo.forEach(dojo.map(rowsToRemove, function(rowIndex){
+ return g._by_idx[rowIndex];
+ }), function(row){
+ if(row){
+ s.deleteItem(row.item);
+ }
+ });
+ s.save({
+ onComplete: function(){
+ dojo.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 = [];
+
+ dojo.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};
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Rearrange/*name:'rearrange'*/);
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Rearrange.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Rearrange.xd.js new file mode 100644 index 0000000..92a434a --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Rearrange.xd.js @@ -0,0 +1,498 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.Rearrange"],
+["require", "dojox.grid.enhanced._Plugin"],
+["require", "dojox.grid.enhanced.plugins._RowMapLayer"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.Rearrange"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Rearrange"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Rearrange");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid.enhanced.plugins._RowMapLayer");
+
+dojo.declare("dojox.grid.enhanced.plugins.Rearrange", dojox.grid.enhanced._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 dojox.grid.enhanced.plugins._RowMapLayer(grid);
+ dojox.grid.enhanced.plugins.wrap(grid, "_storeLayerFetch", rowMapLayer);
+ },
+ setArgs: function(args){
+ this.args = dojo.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(dojo.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;
+ var rightCount = 0;
+ var maxCol = Math.max(colsToMove[colsToMove.length - 1], targetPos);
+ if(maxCol == cells.length){
+ --maxCol;
+ }
+ for(i = colsToMove[0]; i <= maxCol; ++i){
+ var j = tmp[i];
+ if(j >= 0){
+ if(i != targetPos - delta + j){
+ mapping[i] = targetPos - delta + j;
+ }
+ leftCount = j + 1;
+ rightCount = colsToMove.length - j - 1;
+ }else if(i < targetPos && leftCount > 0){
+ mapping[i] = i - leftCount;
+ }else if(i >= targetPos && rightCount > 0){
+ mapping[i] = i + 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;
+ dojo.publish("dojox/grid/rearrange/move/" + g.id, ["col", mapping]);
+ },
+ 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 = {};
+ dojo.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 = {};
+ dojo.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 = dojo.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(){
+ dojo.publish("dojox/grid/rearrange/move/" + g.id, ["row", tmpMapping]);
+ 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;
+ }
+ dojo.forEach(sources, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, "");
+ });
+ dojo.forEach(targets, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, point.v);
+ });
+ s.save({
+ onComplete: function(){
+ dojo.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;
+ }
+ dojo.forEach(targets, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, point.v);
+ });
+ s.save({
+ onComplete: function(){
+ setTimeout(function(){
+ dojo.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;
+ }
+ dojo.forEach(targets, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, point.v);
+ });
+ s.save({
+ onComplete: function(){
+ dojo.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;
+ }
+ dojo.forEach(targets, function(point){
+ s.setValue(g._by_idx[point.r].item, cells[point.c].field, "");
+ });
+ s.save({
+ onComplete: function(){
+ dojo.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,
+ _this = this;
+ var len = rowsToMove.length;
+ 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;
+ for(i = 0; !thisItem; ++i){
+ thisItem = g._by_idx[i];
+ }
+ var attrs = s.getAttributes(thisItem.item);
+ var rowsToFetch = [];
+ dojo.forEach(rowsToMove, function(rowIndex, i){
+ var item = {};
+ var srcItem = srcg._by_idx[rowIndex];
+ if(srcItem){
+ dojo.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 && dojo.isObject(rowsToMove[0])){
+ dojo.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(){
+ dojo.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{
+ dojo.forEach(dojo.map(rowsToRemove, function(rowIndex){
+ return g._by_idx[rowIndex];
+ }), function(row){
+ if(row){
+ s.deleteItem(row.item);
+ }
+ });
+ s.save({
+ onComplete: function(){
+ dojo.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 = [];
+
+ dojo.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};
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Rearrange/*name:'rearrange'*/);
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Search.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Search.js new file mode 100644 index 0000000..c4f6420 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Search.js @@ -0,0 +1,120 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.Search"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Search"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Search");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojo.data.util.filter");
+
+dojo.declare("dojox.grid.enhanced.plugins.Search", dojox.grid.enhanced._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 && dojo.isObject(args)) ? args : {};
+ this._cacheSize = args.cacheSize || -1;
+ grid.searchRow = dojo.hitch(this, "searchRow");
+ },
+ searchRow: function(/* Object|RegExp|String */searchArgs, /* function(Integer, item) */onSearched){
+ if(!dojo.isFunction(onSearched)){ return; }
+ if(dojo.isString(searchArgs)){
+ searchArgs = dojo.data.util.filter.patternToRegExp(searchArgs);
+ }
+ var isGlobal = false;
+ if(searchArgs instanceof RegExp){
+ isGlobal = true;
+ }else if(dojo.isObject(searchArgs)){
+ var isEmpty = true;
+ for(var field in searchArgs){
+ if(dojo.isString(searchArgs[field])){
+ searchArgs[field] = dojo.data.util.filter.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,
+ "onBegin": function(size){
+ _this._storeSize = size;
+ },
+ "onComplete": function(items){
+ if(!dojo.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 = dojo.filter(g.layout.cells, function(cell){
+ return !cell.hidden;
+ });
+ if(isGlobal){
+ return dojo.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;
+ }
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Search/*name:'search'*/);
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Search.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Search.xd.js new file mode 100644 index 0000000..6e19301 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Search.xd.js @@ -0,0 +1,126 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.Search"],
+["require", "dojox.grid.enhanced._Plugin"],
+["require", "dojo.data.util.filter"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.Search"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Search"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Search");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojo.data.util.filter");
+
+dojo.declare("dojox.grid.enhanced.plugins.Search", dojox.grid.enhanced._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 && dojo.isObject(args)) ? args : {};
+ this._cacheSize = args.cacheSize || -1;
+ grid.searchRow = dojo.hitch(this, "searchRow");
+ },
+ searchRow: function(/* Object|RegExp|String */searchArgs, /* function(Integer, item) */onSearched){
+ if(!dojo.isFunction(onSearched)){ return; }
+ if(dojo.isString(searchArgs)){
+ searchArgs = dojo.data.util.filter.patternToRegExp(searchArgs);
+ }
+ var isGlobal = false;
+ if(searchArgs instanceof RegExp){
+ isGlobal = true;
+ }else if(dojo.isObject(searchArgs)){
+ var isEmpty = true;
+ for(var field in searchArgs){
+ if(dojo.isString(searchArgs[field])){
+ searchArgs[field] = dojo.data.util.filter.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,
+ "onBegin": function(size){
+ _this._storeSize = size;
+ },
+ "onComplete": function(items){
+ if(!dojo.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 = dojo.filter(g.layout.cells, function(cell){
+ return !cell.hidden;
+ });
+ if(isGlobal){
+ return dojo.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;
+ }
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Search/*name:'search'*/);
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Selector.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Selector.js new file mode 100644 index 0000000..2511ce1 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Selector.js @@ -0,0 +1,1456 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.Selector"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Selector"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Selector");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid.enhanced.plugins.AutoScroll");
+dojo.require("dojox.grid.cells._base");
+
+(function(){
+/*=====
+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){
+ dojo.stopEvent(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;
+ };
+dojo.declare("dojox.grid.enhanced.plugins.Selector", dojox.grid.enhanced._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",
+/*
+ // _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.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 || !dojo.isObject(config)){
+ return;
+ }
+ var types = ["row", "col", "cell"];
+ for(var type in config){
+ if(dojo.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);
+ 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 dojo.map(this._selected[type], function(item){ return item; });
+ case "col": case "row":
+ return dojo.map(includeExceptions ? this._selected[type]
+ : dojo.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]
+ : dojo.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 = dojo.hitch(g, "onMouseUp");
+ var mouseDown = dojo.hitch(g, "onMouseDown");
+ var doRowSelectorFocus = function(e){
+ e.cellNode.style.border = "solid 1px";
+ };
+ dojo.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("row");
+ 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 dojox.grid._RowSelector){
+ rowSelector.doStyleRowNode = function(inRowIndex, inRowNode){
+ dojo.removeClass(inRowNode, "dojoxGridRow");
+ dojo.addClass(inRowNode, "dojoxGridRowbar");
+ dojo.addClass(inRowNode, "dojoxGridNonNormalizedCell");
+ dojo.toggleClass(inRowNode, "dojoxGridRowbarOver", g.rows.isOver(inRowIndex));
+ dojo.toggleClass(inRowNode, "dojoxGridRowbarSelected", !!g.selection.isSelected(inRowIndex));
+ };
+ }
+ this.connect(g, "updateRow", function(rowIndex){
+ dojo.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 = dojo.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 = dojo.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 = dojo.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(dojo.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;
+ dojo.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){
+ dojo.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);
+ dojo.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);
+
+ dojo.forEach(this._selected.row, function(item){
+ dojo.forEach(this.grid.layout.cells, function(cell){
+ this._highlightNode(cell.getNode(item.row), false);
+ }, this);
+ }, this);
+ //The rowbar must be cleaned manually
+ dojo.query(".dojoxGridRowSelectorSelected").forEach(function(node){
+ dojo.removeClass(node, "dojoxGridRowSelectorSelected");
+ dojo.removeClass(node, "dojoxGridRowSelectorSelectedUp");
+ dojo.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;
+ dojo.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]);
+ dojo.forEach(pointSet, function(item){
+ if(item && !item.converted){
+ var from = item[type];
+ if(from in mapping){
+ item[type] = mapping[from];
+ }
+ item.converted = true;
+ }
+ });
+ dojo.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];
+ }
+ }
+ });
+ }
+
+ dojo.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]){
+ dojo.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, dk = dojo.keys,
+ 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 dk.SPACE:
+ //Keyboard single point selection is SPACE.
+ _this._startSelect(type, getTarget(), evt.ctrlKey, evt.shiftKey);
+ _this._endSelect(type);
+ break;
+ case dk.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 == dojo.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 dojox.grid._RowSelector){
+ this._lastFocusedRowBarIdx = 0;
+ f.addArea({
+ name:"rowHeader",
+ onFocus: function(evt, step){
+ var view = g.views.views[0];
+ if(view instanceof dojox.grid._RowSelector){
+ var rowBarNode = view.getCellNode(_this._lastFocusedRowBarIdx, 0);
+ if(rowBarNode){
+ dojo.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){
+ dijit.focus(rowBarNode);
+ dojo.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 dojox.grid._RowSelector){
+ var rowBarNode = view.getCellNode(_this._lastFocusedRowBarIdx, 0);
+ dojo.toggleClass(rowBarNode, f.focusClass, false);
+ _stopEvent(evt);
+ }
+ return true;
+ },
+ onMove: function(rowStep, colStep, evt){
+ var view = g.views.views[0];
+ if(rowStep && view instanceof dojox.grid._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);
+ dojo.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);
+ dijit.focus(rowBarNode);
+ dojo.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: dojo.partial(onmove, "cell", function(type, rowStep, colStep, evt){
+ var current = _this._currentPoint[type];
+ return _createItem("cell", current.row + rowStep, current.col + colStep);
+ }),
+ onKeyDown: dojo.partial(onkeydown, "cell", function(){
+ return _createItem("cell", f.rowIndex, f.cell.index);
+ }),
+ onKeyUp: dojo.partial(onkeyup, "cell")
+ });
+ f.placeArea("cellselect","below","content");
+ f.addArea({
+ name:"colselect",
+ onMove: dojo.partial(onmove, "col", function(type, rowStep, colStep, evt){
+ var current = _this._currentPoint[type];
+ return _createItem("col", current.col + colStep);
+ }),
+ onKeyDown: dojo.partial(onkeydown, "col", function(){
+ return _createItem("col", f.getHeaderIndex());
+ }),
+ onKeyUp: dojo.partial(onkeyup, "col")
+ });
+ f.placeArea("colselect","below","header");
+ f.addArea({
+ name:"rowselect",
+ onMove: dojo.partial(onmove, "row", function(type, rowStep, colStep, evt){
+ return _createItem("row", f.rowIndex);
+ }),
+ onKeyDown: dojo.partial(onkeydown, "row", function(){
+ return _createItem("row", f.rowIndex);
+ }),
+ onKeyUp: dojo.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;
+ dojo.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 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("all", 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){
+ 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";
+ dojo.toggleClass(node, selectCSSClass, toHighlight);
+ dojo.toggleClass(node, selectCellClass, toHighlight);
+ }
+ },
+ _highlightHeader: function(colIdx, toHighlight){
+ var cells = this.grid.layout.cells;
+ var node = cells[colIdx].getHeaderNode();
+ var selectedClass = "dojoxGridHeaderSelected";
+ dojo.toggleClass(node, selectedClass, toHighlight);
+ },
+ _highlightRowSelector: function(rowIdx, toHighlight){
+ //var t1 = (new Date()).getTime();
+ var rowSelector = this.grid.views.views[0];
+ if(rowSelector instanceof dojox.grid._RowSelector){
+ var node = rowSelector.getRowNode(rowIdx);
+ if(node){
+ var selectedClass = "dojoxGridRowSelectorSelected";
+ dojo.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);
+ dojo.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);
+ dojo.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
+ dojo.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 = [];
+ dojo.forEach(this._selected[type], function(v1){
+ dojo.forEach(newCellItems, function(v2){
+ if(v1[type] == v2[type]){
+ var pos = dojo.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 = [];
+ dojo.forEach(this._selected.cell, function(v1){
+ dojo.some(newItems, function(v2){
+ if(v1[type] == v2[type]){
+ toRemove.push(v1);
+ return true;
+ }
+ return false;
+ });
+ });
+ this._remove("cell", toRemove);
+ dojo.forEach(this._selected[_theOther[type]], function(v1){
+ dojo.forEach(newItems, function(v2){
+ var pos = dojo.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.
+ dojo.forEach(this._selected[type], function(v1){
+ dojo.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.
+ dojo.forEach(this._selected[type], function(v1){
+ dojo.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 = dojo.filter(items, function(item){
+ return dojo.indexOf(colMakedup, item) < 0 && dojo.indexOf(rowMakedup, item) < 0 &&
+ !cells[item.col].hidden && !cells[item.col].notselectable;
+ });
+ }else{
+ if(type == "col"){
+ //Step over hidden columns.
+ items = dojo.filter(items, function(item){
+ return !cells[item.col].hidden && !cells[item.col].notselectable;
+ });
+ }
+ this._makeupForCells(type, items);
+ this._selected[type] = dojo.filter(this._selected[type], function(v){
+ return dojo.every(items, function(item){
+ return v[type] !== item[type];
+ });
+ });
+ }
+ if(type != "col" && this.grid._hasIdentity){
+ dojo.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 = dojo.partial(_isEqual, type);
+ this._selected[type] = dojo.filter(this._selected[type], function(v1){
+ return !dojo.some(items, function(v2){
+ return comp(v1, v2);
+ });
+ });
+ if(type == "cell"){
+ this._addCellException("col", items);
+ this._addCellException("row", items);
+ }else{
+ 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 dojo.some(this._selected[type], function(v){
+ return v[type] == attr && dojo.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 = dojo.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 && dojo.isArray(item.except) &&
+ (allowNotSelectable || !g.layout.cells[index].notselectable);
+ case "row":
+ return index >= 0 && index < g.rowCount && dojo.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;
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Selector/*name:'selector'*/, {
+ "dependency": ["autoScroll"]
+});
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/Selector.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/Selector.xd.js new file mode 100644 index 0000000..694c36f --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/Selector.xd.js @@ -0,0 +1,1463 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.Selector"],
+["require", "dojox.grid.enhanced._Plugin"],
+["require", "dojox.grid.enhanced.plugins.AutoScroll"],
+["require", "dojox.grid.cells._base"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.Selector"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.Selector"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.Selector");
+
+dojo.require("dojox.grid.enhanced._Plugin");
+dojo.require("dojox.grid.enhanced.plugins.AutoScroll");
+dojo.require("dojox.grid.cells._base");
+
+(function(){
+/*=====
+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){
+ dojo.stopEvent(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;
+ };
+dojo.declare("dojox.grid.enhanced.plugins.Selector", dojox.grid.enhanced._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",
+/*
+ // _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.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 || !dojo.isObject(config)){
+ return;
+ }
+ var types = ["row", "col", "cell"];
+ for(var type in config){
+ if(dojo.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);
+ 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 dojo.map(this._selected[type], function(item){ return item; });
+ case "col": case "row":
+ return dojo.map(includeExceptions ? this._selected[type]
+ : dojo.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]
+ : dojo.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 = dojo.hitch(g, "onMouseUp");
+ var mouseDown = dojo.hitch(g, "onMouseDown");
+ var doRowSelectorFocus = function(e){
+ e.cellNode.style.border = "solid 1px";
+ };
+ dojo.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("row");
+ 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 dojox.grid._RowSelector){
+ rowSelector.doStyleRowNode = function(inRowIndex, inRowNode){
+ dojo.removeClass(inRowNode, "dojoxGridRow");
+ dojo.addClass(inRowNode, "dojoxGridRowbar");
+ dojo.addClass(inRowNode, "dojoxGridNonNormalizedCell");
+ dojo.toggleClass(inRowNode, "dojoxGridRowbarOver", g.rows.isOver(inRowIndex));
+ dojo.toggleClass(inRowNode, "dojoxGridRowbarSelected", !!g.selection.isSelected(inRowIndex));
+ };
+ }
+ this.connect(g, "updateRow", function(rowIndex){
+ dojo.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 = dojo.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 = dojo.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 = dojo.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(dojo.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;
+ dojo.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){
+ dojo.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);
+ dojo.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);
+
+ dojo.forEach(this._selected.row, function(item){
+ dojo.forEach(this.grid.layout.cells, function(cell){
+ this._highlightNode(cell.getNode(item.row), false);
+ }, this);
+ }, this);
+ //The rowbar must be cleaned manually
+ dojo.query(".dojoxGridRowSelectorSelected").forEach(function(node){
+ dojo.removeClass(node, "dojoxGridRowSelectorSelected");
+ dojo.removeClass(node, "dojoxGridRowSelectorSelectedUp");
+ dojo.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;
+ dojo.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]);
+ dojo.forEach(pointSet, function(item){
+ if(item && !item.converted){
+ var from = item[type];
+ if(from in mapping){
+ item[type] = mapping[from];
+ }
+ item.converted = true;
+ }
+ });
+ dojo.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];
+ }
+ }
+ });
+ }
+
+ dojo.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]){
+ dojo.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, dk = dojo.keys,
+ 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 dk.SPACE:
+ //Keyboard single point selection is SPACE.
+ _this._startSelect(type, getTarget(), evt.ctrlKey, evt.shiftKey);
+ _this._endSelect(type);
+ break;
+ case dk.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 == dojo.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 dojox.grid._RowSelector){
+ this._lastFocusedRowBarIdx = 0;
+ f.addArea({
+ name:"rowHeader",
+ onFocus: function(evt, step){
+ var view = g.views.views[0];
+ if(view instanceof dojox.grid._RowSelector){
+ var rowBarNode = view.getCellNode(_this._lastFocusedRowBarIdx, 0);
+ if(rowBarNode){
+ dojo.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){
+ dijit.focus(rowBarNode);
+ dojo.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 dojox.grid._RowSelector){
+ var rowBarNode = view.getCellNode(_this._lastFocusedRowBarIdx, 0);
+ dojo.toggleClass(rowBarNode, f.focusClass, false);
+ _stopEvent(evt);
+ }
+ return true;
+ },
+ onMove: function(rowStep, colStep, evt){
+ var view = g.views.views[0];
+ if(rowStep && view instanceof dojox.grid._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);
+ dojo.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);
+ dijit.focus(rowBarNode);
+ dojo.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: dojo.partial(onmove, "cell", function(type, rowStep, colStep, evt){
+ var current = _this._currentPoint[type];
+ return _createItem("cell", current.row + rowStep, current.col + colStep);
+ }),
+ onKeyDown: dojo.partial(onkeydown, "cell", function(){
+ return _createItem("cell", f.rowIndex, f.cell.index);
+ }),
+ onKeyUp: dojo.partial(onkeyup, "cell")
+ });
+ f.placeArea("cellselect","below","content");
+ f.addArea({
+ name:"colselect",
+ onMove: dojo.partial(onmove, "col", function(type, rowStep, colStep, evt){
+ var current = _this._currentPoint[type];
+ return _createItem("col", current.col + colStep);
+ }),
+ onKeyDown: dojo.partial(onkeydown, "col", function(){
+ return _createItem("col", f.getHeaderIndex());
+ }),
+ onKeyUp: dojo.partial(onkeyup, "col")
+ });
+ f.placeArea("colselect","below","header");
+ f.addArea({
+ name:"rowselect",
+ onMove: dojo.partial(onmove, "row", function(type, rowStep, colStep, evt){
+ return _createItem("row", f.rowIndex);
+ }),
+ onKeyDown: dojo.partial(onkeydown, "row", function(){
+ return _createItem("row", f.rowIndex);
+ }),
+ onKeyUp: dojo.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;
+ dojo.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 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("all", 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){
+ 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";
+ dojo.toggleClass(node, selectCSSClass, toHighlight);
+ dojo.toggleClass(node, selectCellClass, toHighlight);
+ }
+ },
+ _highlightHeader: function(colIdx, toHighlight){
+ var cells = this.grid.layout.cells;
+ var node = cells[colIdx].getHeaderNode();
+ var selectedClass = "dojoxGridHeaderSelected";
+ dojo.toggleClass(node, selectedClass, toHighlight);
+ },
+ _highlightRowSelector: function(rowIdx, toHighlight){
+ //var t1 = (new Date()).getTime();
+ var rowSelector = this.grid.views.views[0];
+ if(rowSelector instanceof dojox.grid._RowSelector){
+ var node = rowSelector.getRowNode(rowIdx);
+ if(node){
+ var selectedClass = "dojoxGridRowSelectorSelected";
+ dojo.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);
+ dojo.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);
+ dojo.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
+ dojo.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 = [];
+ dojo.forEach(this._selected[type], function(v1){
+ dojo.forEach(newCellItems, function(v2){
+ if(v1[type] == v2[type]){
+ var pos = dojo.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 = [];
+ dojo.forEach(this._selected.cell, function(v1){
+ dojo.some(newItems, function(v2){
+ if(v1[type] == v2[type]){
+ toRemove.push(v1);
+ return true;
+ }
+ return false;
+ });
+ });
+ this._remove("cell", toRemove);
+ dojo.forEach(this._selected[_theOther[type]], function(v1){
+ dojo.forEach(newItems, function(v2){
+ var pos = dojo.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.
+ dojo.forEach(this._selected[type], function(v1){
+ dojo.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.
+ dojo.forEach(this._selected[type], function(v1){
+ dojo.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 = dojo.filter(items, function(item){
+ return dojo.indexOf(colMakedup, item) < 0 && dojo.indexOf(rowMakedup, item) < 0 &&
+ !cells[item.col].hidden && !cells[item.col].notselectable;
+ });
+ }else{
+ if(type == "col"){
+ //Step over hidden columns.
+ items = dojo.filter(items, function(item){
+ return !cells[item.col].hidden && !cells[item.col].notselectable;
+ });
+ }
+ this._makeupForCells(type, items);
+ this._selected[type] = dojo.filter(this._selected[type], function(v){
+ return dojo.every(items, function(item){
+ return v[type] !== item[type];
+ });
+ });
+ }
+ if(type != "col" && this.grid._hasIdentity){
+ dojo.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 = dojo.partial(_isEqual, type);
+ this._selected[type] = dojo.filter(this._selected[type], function(v1){
+ return !dojo.some(items, function(v2){
+ return comp(v1, v2);
+ });
+ });
+ if(type == "cell"){
+ this._addCellException("col", items);
+ this._addCellException("row", items);
+ }else{
+ 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 dojo.some(this._selected[type], function(v){
+ return v[type] == attr && dojo.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 = dojo.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 && dojo.isArray(item.except) &&
+ (allowNotSelectable || !g.layout.cells[index].notselectable);
+ case "row":
+ return index >= 0 && index < g.rowCount && dojo.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;
+ }
+});
+dojox.grid.EnhancedGrid.registerPlugin(dojox.grid.enhanced.plugins.Selector/*name:'selector'*/, {
+ "dependency": ["autoScroll"]
+});
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/_RowMapLayer.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/_RowMapLayer.js new file mode 100644 index 0000000..6b0347f --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/_RowMapLayer.js @@ -0,0 +1,215 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins._RowMapLayer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins._RowMapLayer"] = true;
+dojo.provide("dojox.grid.enhanced.plugins._RowMapLayer");
+
+dojo.require("dojox.grid.enhanced.plugins._StoreLayer");
+
+(function(){
+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 ? dojo.hitch(scope || dojo.global, func) : function(){};
+};
+
+dojo.declare("dojox.grid.enhanced.plugins._RowMapLayer", dojox.grid.enhanced.plugins._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 dojo.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){
+ dojo.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-1.6/dojox/grid/enhanced/plugins/_RowMapLayer.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/_RowMapLayer.xd.js new file mode 100644 index 0000000..3483c0f --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/_RowMapLayer.xd.js @@ -0,0 +1,220 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins._RowMapLayer"],
+["require", "dojox.grid.enhanced.plugins._StoreLayer"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins._RowMapLayer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins._RowMapLayer"] = true;
+dojo.provide("dojox.grid.enhanced.plugins._RowMapLayer");
+
+dojo.require("dojox.grid.enhanced.plugins._StoreLayer");
+
+(function(){
+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 ? dojo.hitch(scope || dojo.global, func) : function(){};
+};
+
+dojo.declare("dojox.grid.enhanced.plugins._RowMapLayer", dojox.grid.enhanced.plugins._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 dojo.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){
+ dojo.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-1.6/dojox/grid/enhanced/plugins/_SelectionPreserver.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/_SelectionPreserver.js new file mode 100644 index 0000000..65c95ad --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/_SelectionPreserver.js @@ -0,0 +1,138 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins._SelectionPreserver"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins._SelectionPreserver"] = true;
+dojo.provide("dojox.grid.enhanced.plugins._SelectionPreserver");
+
+dojo.declare("dojox.grid.enhanced.plugins._SelectionPreserver", null, {
+ // summary:
+ // Preserve selections across various user actions.
+ //
+ // description:
+ // When this feature turned on, Grid will try to preserve selections across various user actions, e.g. sorting, filtering 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 selected by range previously(e.g.SHIFT + click)
+ //
+ // example:
+ // | //To turn on this - set 'keepSelection' attribute to true
+ // | <div dojoType="dojox.grid.EnhancedGrid" keepSelection = true .../>
+
+ //_connects: Array
+ // List of all connections.
+ _connects: [],
+
+ constructor: function(selection){
+ this.selection = selection;
+ var grid = this.grid = selection.grid;
+ grid.onSelectedById = this.onSelectedById;
+ this.reset();
+
+ var oldClearData = grid._clearData;
+ var _this = this;
+ grid._clearData = function(){
+ _this._updateMapping(!grid._noInternalMapping);
+ _this._trustSelection = [];
+ oldClearData.apply(grid, arguments);
+ };
+ this.connect(grid, '_setStore', 'reset');
+ this.connect(grid, '_addItem', '_reSelectById');
+ this.connect(selection, 'addToSelection', dojo.hitch(this, '_selectById', true));
+ this.connect(selection, 'deselect', dojo.hitch(this, '_selectById', false));
+ this.connect(selection, 'selectRange', dojo.hitch(this, '_updateMapping', true, true, false));
+ this.connect(selection, 'deselectRange', dojo.hitch(this, '_updateMapping', true, false, false));
+ this.connect(selection, 'deselectAll', dojo.hitch(this, '_updateMapping', true, false, true));
+ },
+ destroy: function(){
+ this.reset();
+ dojo.forEach(this._connects, dojo.disconnect);
+ delete this._connects;
+ },
+ connect: function(obj, event, method){
+ // summary:
+ // Connects specified obj/event to specified method of this object.
+ var conn = dojo.connect(obj, event, this, method);
+ this._connects.push(conn);
+ return conn;
+ },
+ reset: function(){
+ this._idMap = [];
+ this._selectedById = {};
+ this._trustSelection = [];
+ this._defaultSelected = false;
+ },
+ _reSelectById: function(item, index){
+ // summary:
+ // When some rows is fetched, determine whether it should be selected.
+ // When this function is called, grid.selection.selected[] is not trustable.
+ 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:
+ // Record selected rows by ID.
+ if(this.selection.mode == 'none' || !this.grid._hasIdentity){ return; }
+ var item = inItemOrIndex;
+ if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
+ var entry = this.grid._by_idx[inItemOrIndex];
+ item = entry && entry.item;
+ }
+ if(item){
+ var id = this.grid.store.getIdentity(item);
+ this._selectedById[id] = !!toSelect;
+ }else{
+ this._trustSelection[inItemOrIndex] = true;
+ }
+ },
+ onSelectedById: function(id, rowIndex, value){},
+
+ _updateMapping: function(trustSelection, isSelect, isForAll, from, to){
+ // summary:
+ // This function trys 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){
+ for(i = this._idMap.length; i >= 0; --i){
+ this._selectedById[this._idMap[i]] = isSelect;
+ }
+ }
+ }
+});
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/_SelectionPreserver.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/_SelectionPreserver.xd.js new file mode 100644 index 0000000..8167602 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/_SelectionPreserver.xd.js @@ -0,0 +1,142 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins._SelectionPreserver"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins._SelectionPreserver"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins._SelectionPreserver"] = true;
+dojo.provide("dojox.grid.enhanced.plugins._SelectionPreserver");
+
+dojo.declare("dojox.grid.enhanced.plugins._SelectionPreserver", null, {
+ // summary:
+ // Preserve selections across various user actions.
+ //
+ // description:
+ // When this feature turned on, Grid will try to preserve selections across various user actions, e.g. sorting, filtering 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 selected by range previously(e.g.SHIFT + click)
+ //
+ // example:
+ // | //To turn on this - set 'keepSelection' attribute to true
+ // | <div dojoType="dojox.grid.EnhancedGrid" keepSelection = true .../>
+
+ //_connects: Array
+ // List of all connections.
+ _connects: [],
+
+ constructor: function(selection){
+ this.selection = selection;
+ var grid = this.grid = selection.grid;
+ grid.onSelectedById = this.onSelectedById;
+ this.reset();
+
+ var oldClearData = grid._clearData;
+ var _this = this;
+ grid._clearData = function(){
+ _this._updateMapping(!grid._noInternalMapping);
+ _this._trustSelection = [];
+ oldClearData.apply(grid, arguments);
+ };
+ this.connect(grid, '_setStore', 'reset');
+ this.connect(grid, '_addItem', '_reSelectById');
+ this.connect(selection, 'addToSelection', dojo.hitch(this, '_selectById', true));
+ this.connect(selection, 'deselect', dojo.hitch(this, '_selectById', false));
+ this.connect(selection, 'selectRange', dojo.hitch(this, '_updateMapping', true, true, false));
+ this.connect(selection, 'deselectRange', dojo.hitch(this, '_updateMapping', true, false, false));
+ this.connect(selection, 'deselectAll', dojo.hitch(this, '_updateMapping', true, false, true));
+ },
+ destroy: function(){
+ this.reset();
+ dojo.forEach(this._connects, dojo.disconnect);
+ delete this._connects;
+ },
+ connect: function(obj, event, method){
+ // summary:
+ // Connects specified obj/event to specified method of this object.
+ var conn = dojo.connect(obj, event, this, method);
+ this._connects.push(conn);
+ return conn;
+ },
+ reset: function(){
+ this._idMap = [];
+ this._selectedById = {};
+ this._trustSelection = [];
+ this._defaultSelected = false;
+ },
+ _reSelectById: function(item, index){
+ // summary:
+ // When some rows is fetched, determine whether it should be selected.
+ // When this function is called, grid.selection.selected[] is not trustable.
+ 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:
+ // Record selected rows by ID.
+ if(this.selection.mode == 'none' || !this.grid._hasIdentity){ return; }
+ var item = inItemOrIndex;
+ if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
+ var entry = this.grid._by_idx[inItemOrIndex];
+ item = entry && entry.item;
+ }
+ if(item){
+ var id = this.grid.store.getIdentity(item);
+ this._selectedById[id] = !!toSelect;
+ }else{
+ this._trustSelection[inItemOrIndex] = true;
+ }
+ },
+ onSelectedById: function(id, rowIndex, value){},
+
+ _updateMapping: function(trustSelection, isSelect, isForAll, from, to){
+ // summary:
+ // This function trys 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){
+ for(i = this._idMap.length; i >= 0; --i){
+ this._selectedById[this._idMap[i]] = isSelect;
+ }
+ }
+ }
+});
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/_StoreLayer.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/_StoreLayer.js new file mode 100644 index 0000000..153fdf3 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/_StoreLayer.js @@ -0,0 +1,394 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins._StoreLayer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins._StoreLayer"] = true;
+dojo.provide("dojox.grid.enhanced.plugins._StoreLayer");
+// 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.
+(function(){
+ var ns = dojox.grid.enhanced.plugins,
+
+ getPrevTags = function(tags){
+ var tagList = ["reorder", "sizeChange", "normal", "presentation"];
+ var idx = tagList.length;
+ for(var i = tags.length - 1; i >= 0; --i){
+ var p = dojo.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 = dojo.hitch(store, getLayer);
+ store.unwrap = dojo.hitch(store, unwrap);
+ store.forEachLayer = dojo.hitch(store, forEachLayer);
+ }
+ var prevTags = getPrevTags(layer.tags);
+ if(!dojo.some(store._layers, function(lyr, i){
+ if(dojo.some(lyr.tags, function(tag){
+ return dojo.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
+ };
+
+ dojo.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 = dojo.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 (dojo.hitch(this._store, this._originFetch)).apply(this, arguments);
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins._ServerSideLayer", ns._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.
+ dojo.xhrPost({
+ url: this._url || this._store.url,
+ content: this.__cmds,
+ load: dojo.hitch(this, function(responce){
+ this.onCommandLoad(responce, userRequest);
+ this.originFetch(userRequest);
+ }),
+ error: dojo.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;
+ }
+ });
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/_StoreLayer.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/_StoreLayer.xd.js new file mode 100644 index 0000000..a5dfb72 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/_StoreLayer.xd.js @@ -0,0 +1,398 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins._StoreLayer"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins._StoreLayer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins._StoreLayer"] = true;
+dojo.provide("dojox.grid.enhanced.plugins._StoreLayer");
+// 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.
+(function(){
+ var ns = dojox.grid.enhanced.plugins,
+
+ getPrevTags = function(tags){
+ var tagList = ["reorder", "sizeChange", "normal", "presentation"];
+ var idx = tagList.length;
+ for(var i = tags.length - 1; i >= 0; --i){
+ var p = dojo.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 = dojo.hitch(store, getLayer);
+ store.unwrap = dojo.hitch(store, unwrap);
+ store.forEachLayer = dojo.hitch(store, forEachLayer);
+ }
+ var prevTags = getPrevTags(layer.tags);
+ if(!dojo.some(store._layers, function(lyr, i){
+ if(dojo.some(lyr.tags, function(tag){
+ return dojo.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
+ };
+
+ dojo.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 = dojo.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 (dojo.hitch(this._store, this._originFetch)).apply(this, arguments);
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins._ServerSideLayer", ns._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.
+ dojo.xhrPost({
+ url: this._url || this._store.url,
+ content: this.__cmds,
+ load: dojo.hitch(this, function(responce){
+ this.onCommandLoad(responce, userRequest);
+ this.originFetch(userRequest);
+ }),
+ error: dojo.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;
+ }
+ });
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/CSVWriter.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/CSVWriter.js new file mode 100644 index 0000000..697cd94 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/CSVWriter.js @@ -0,0 +1,90 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.exporter.CSVWriter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.exporter.CSVWriter"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.exporter.CSVWriter");
+
+dojo.require("dojox.grid.enhanced.plugins.exporter._ExportWriter");
+
+dojox.grid.enhanced.plugins.Exporter.registerWriter("csv",
+ "dojox.grid.enhanced.plugins.exporter.CSVWriter");
+
+dojo.declare("dojox.grid.enhanced.plugins.exporter.CSVWriter",
+ dojox.grid.enhanced.plugins.exporter._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;
+ dojo.forEach(arg_obj.grid.layout.cells, function(cell){
+ //We are not interested in indirect selectors and row indexes.
+ if(!cell.hidden && dojo.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 && dojo.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-1.6/dojox/grid/enhanced/plugins/exporter/CSVWriter.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/CSVWriter.xd.js new file mode 100644 index 0000000..16634fa --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/CSVWriter.xd.js @@ -0,0 +1,95 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.exporter.CSVWriter"],
+["require", "dojox.grid.enhanced.plugins.exporter._ExportWriter"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.exporter.CSVWriter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.exporter.CSVWriter"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.exporter.CSVWriter");
+
+dojo.require("dojox.grid.enhanced.plugins.exporter._ExportWriter");
+
+dojox.grid.enhanced.plugins.Exporter.registerWriter("csv",
+ "dojox.grid.enhanced.plugins.exporter.CSVWriter");
+
+dojo.declare("dojox.grid.enhanced.plugins.exporter.CSVWriter",
+ dojox.grid.enhanced.plugins.exporter._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;
+ dojo.forEach(arg_obj.grid.layout.cells, function(cell){
+ //We are not interested in indirect selectors and row indexes.
+ if(!cell.hidden && dojo.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 && dojo.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-1.6/dojox/grid/enhanced/plugins/exporter/TableWriter.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/TableWriter.js new file mode 100644 index 0000000..ce23a72 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/TableWriter.js @@ -0,0 +1,156 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.exporter.TableWriter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.exporter.TableWriter"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.exporter.TableWriter");
+
+dojo.require("dojox.grid.enhanced.plugins.exporter._ExportWriter");
+
+dojox.grid.enhanced.plugins.Exporter.registerWriter("table",
+ "dojox.grid.enhanced.plugins.exporter.TableWriter");
+
+dojo.declare("dojox.grid.enhanced.plugins.exporter.TableWriter",
+ dojox.grid.enhanced.plugins.exporter._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_", 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],
+ tagName, height,
+ width = dojo.marginBox(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] = ['<table class="grid_view" style="position: absolute; top: 0; left:', left,
+ 'px;"', this._getTableAttrs("table"), '>'];
+ }
+ table._width = width;
+ if(arg_obj.isHeader){
+ tagName = 'thead';
+ height = dojo.contentBox(arg_obj.view.headerContentNode).h;
+ }else{
+ tagName = 'tbody';
+ var rowNode = arg_obj.grid.getRowNode(arg_obj.rowIdx);
+ if(rowNode){
+ height = dojo.contentBox(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('<',tagName,
+ ' style="height:', height, 'px; width:', width, 'px;"',
+ ' class="', this._getRowClass(arg_obj), '"',
+ this._getTableAttrs(tagName), '>');
+ return true; //Boolean
+ },
+ afterView: function(/* object */arg_obj){
+ // summary:
+ // Overrided from _ExportWriter
+ this._viewTables[arg_obj.viewIdx].push(arg_obj.isHeader ? '</thead>' : '</tbody>');
+ },
+ 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 || dojo.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: ', dojo.contentBox(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
+ dojo.forEach(this._viewTables, function(table){
+ table.push('</table>');
+ });
+ },
+ toString: function(){
+ // summary:
+ // Overrided from _ExportWriter
+ var viewsHTML = dojo.map(this._viewTables, function(table){ //String
+ return table.join('');
+ }).join('');
+ return ['<div style="position: relative;">', viewsHTML, '</div>'].join('');
+ }
+});
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/TableWriter.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/TableWriter.xd.js new file mode 100644 index 0000000..9da1dc0 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/TableWriter.xd.js @@ -0,0 +1,161 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.exporter.TableWriter"],
+["require", "dojox.grid.enhanced.plugins.exporter._ExportWriter"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.exporter.TableWriter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.exporter.TableWriter"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.exporter.TableWriter");
+
+dojo.require("dojox.grid.enhanced.plugins.exporter._ExportWriter");
+
+dojox.grid.enhanced.plugins.Exporter.registerWriter("table",
+ "dojox.grid.enhanced.plugins.exporter.TableWriter");
+
+dojo.declare("dojox.grid.enhanced.plugins.exporter.TableWriter",
+ dojox.grid.enhanced.plugins.exporter._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_", 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],
+ tagName, height,
+ width = dojo.marginBox(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] = ['<table class="grid_view" style="position: absolute; top: 0; left:', left,
+ 'px;"', this._getTableAttrs("table"), '>'];
+ }
+ table._width = width;
+ if(arg_obj.isHeader){
+ tagName = 'thead';
+ height = dojo.contentBox(arg_obj.view.headerContentNode).h;
+ }else{
+ tagName = 'tbody';
+ var rowNode = arg_obj.grid.getRowNode(arg_obj.rowIdx);
+ if(rowNode){
+ height = dojo.contentBox(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('<',tagName,
+ ' style="height:', height, 'px; width:', width, 'px;"',
+ ' class="', this._getRowClass(arg_obj), '"',
+ this._getTableAttrs(tagName), '>');
+ return true; //Boolean
+ },
+ afterView: function(/* object */arg_obj){
+ // summary:
+ // Overrided from _ExportWriter
+ this._viewTables[arg_obj.viewIdx].push(arg_obj.isHeader ? '</thead>' : '</tbody>');
+ },
+ 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 || dojo.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: ', dojo.contentBox(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
+ dojo.forEach(this._viewTables, function(table){
+ table.push('</table>');
+ });
+ },
+ toString: function(){
+ // summary:
+ // Overrided from _ExportWriter
+ var viewsHTML = dojo.map(this._viewTables, function(table){ //String
+ return table.join('');
+ }).join('');
+ return ['<div style="position: relative;">', viewsHTML, '</div>'].join('');
+ }
+});
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/_ExportWriter.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/_ExportWriter.js new file mode 100644 index 0000000..48e1e37 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/_ExportWriter.js @@ -0,0 +1,278 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.exporter._ExportWriter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.exporter._ExportWriter"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.exporter._ExportWriter");
+
+//require Exporter here, so the implementations only need to require this file,
+//and the users only need to require the implementation file.
+dojo.require("dojox.grid.enhanced.plugins.Exporter");
+
+dojo.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-1.6/dojox/grid/enhanced/plugins/exporter/_ExportWriter.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/_ExportWriter.xd.js new file mode 100644 index 0000000..77e7570 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/exporter/_ExportWriter.xd.js @@ -0,0 +1,283 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.exporter._ExportWriter"],
+["require", "dojox.grid.enhanced.plugins.Exporter"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.exporter._ExportWriter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.exporter._ExportWriter"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.exporter._ExportWriter");
+
+//require Exporter here, so the implementations only need to require this file,
+//and the users only need to require the implementation file.
+dojo.require("dojox.grid.enhanced.plugins.Exporter");
+
+dojo.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-1.6/dojox/grid/enhanced/plugins/filter/ClearFilterConfirm.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/ClearFilterConfirm.js new file mode 100644 index 0000000..9b072d2 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/ClearFilterConfirm.js @@ -0,0 +1,44 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter.ClearFilterConfirm"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter.ClearFilterConfirm"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter.ClearFilterConfirm");
+
+dojo.require("dijit.form.Button");
+
+dojo.declare("dojox.grid.enhanced.plugins.filter.ClearFilterConfirm",[dijit._Widget,dijit._Templated],{
+ // summary:
+ // The UI for user to confirm the operation of clearing filter.
+ templateString: dojo.cache("dojox.grid", "enhanced/templates/ClearFilterConfirmPane.html", "<div class=\"dojoxGridClearFilterConfirm\">\r\n\t<div class=\"dojoxGridClearFilterMsg\">\r\n\t\t${_clearFilterMsg}\r\n\t</div>\r\n\t<div class=\"dojoxGridClearFilterBtns\" dojoAttachPoint=\"btnsNode\">\r\n\t\t<span dojoType=\"dijit.form.Button\" label=\"${_cancelBtnLabel}\" dojoAttachPoint=\"cancelBtn\" dojoAttachEvent=\"onClick:_onCancel\"></span>\r\n\t\t<span dojoType=\"dijit.form.Button\" label=\"${_clearBtnLabel}\" dojoAttachPoint=\"clearBtn\" dojoAttachEvent=\"onClick:_onClear\"></span>\r\n\t</div>\r\n</div>\r\n"),
+ 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);
+ dijit.setWaiState(this.cancelBtn.domNode, "label", this.plugin.nls["waiCancelButton"]);
+ dijit.setWaiState(this.clearBtn.domNode, "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-1.6/dojox/grid/enhanced/plugins/filter/ClearFilterConfirm.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/ClearFilterConfirm.xd.js new file mode 100644 index 0000000..20f8ed7 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/ClearFilterConfirm.xd.js @@ -0,0 +1,49 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.filter.ClearFilterConfirm"],
+["require", "dijit.form.Button"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter.ClearFilterConfirm"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter.ClearFilterConfirm"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter.ClearFilterConfirm");
+
+dojo.require("dijit.form.Button");
+
+dojo.declare("dojox.grid.enhanced.plugins.filter.ClearFilterConfirm",[dijit._Widget,dijit._Templated],{
+ // summary:
+ // The UI for user to confirm the operation of clearing filter.
+ templateString: dojo.cache("dojox.grid", "enhanced/templates/ClearFilterConfirmPane.html", "<div class=\"dojoxGridClearFilterConfirm\">\r\n\t<div class=\"dojoxGridClearFilterMsg\">\r\n\t\t${_clearFilterMsg}\r\n\t</div>\r\n\t<div class=\"dojoxGridClearFilterBtns\" dojoAttachPoint=\"btnsNode\">\r\n\t\t<span dojoType=\"dijit.form.Button\" label=\"${_cancelBtnLabel}\" dojoAttachPoint=\"cancelBtn\" dojoAttachEvent=\"onClick:_onCancel\"></span>\r\n\t\t<span dojoType=\"dijit.form.Button\" label=\"${_clearBtnLabel}\" dojoAttachPoint=\"clearBtn\" dojoAttachEvent=\"onClick:_onClear\"></span>\r\n\t</div>\r\n</div>\r\n"),
+ 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);
+ dijit.setWaiState(this.cancelBtn.domNode, "label", this.plugin.nls["waiCancelButton"]);
+ dijit.setWaiState(this.clearBtn.domNode, "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-1.6/dojox/grid/enhanced/plugins/filter/FilterBar.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterBar.js new file mode 100644 index 0000000..def0c38 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterBar.js @@ -0,0 +1,380 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterBar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterBar"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter.FilterBar");
+
+dojo.require("dijit.form.Button");
+dojo.require("dojo.string");
+dojo.require("dojo.fx");
+
+(function(){
+var _focusClass = "dojoxGridFBarHover",
+ _filteredClass = "dojoxGridFBarFiltered",
+ _stopEvent = function(evt){
+ try{
+ if(evt && evt.preventDefault){
+ dojo.stopEvent(evt);
+ }
+ }catch(e){}
+ };
+
+dojo.declare("dojox.grid.enhanced.plugins.filter.FilterBar",[dijit._Widget, dijit._Templated],{
+ // summary:
+ // The filter bar UI.
+ templateString: dojo.cache("dojox.grid", "enhanced/templates/FilterBar.html", "<table class=\"dojoxGridFBar\" border=\"0\" cellspacing=\"0\" dojoAttachEvent=\"onclick:_onClickFilterBar, onmouseenter:_onMouseEnter, onmouseleave:_onMouseLeave, onmousemove:_onMouseMove\"\r\n\t><tr><td class=\"dojoxGridFBarBtnTD\"\r\n\t\t><span dojoType=\"dijit.form.Button\" class=\"dojoxGridFBarBtn\" dojoAttachPoint=\"defineFilterButton\" label=\"...\" iconClass=\"dojoxGridFBarDefFilterBtnIcon\" showLabel=\"true\" dojoAttachEvent=\"onClick:_showFilterDefDialog, onMouseEnter:_onEnterButton, onMouseLeave:_onLeaveButton, onMouseMove:_onMoveButton\"></span\r\n\t></td><td class=\"dojoxGridFBarInfoTD\"\r\n\t\t><span class=\"dojoxGridFBarInner\"\r\n\t\t\t><span class=\"dojoxGridFBarStatus\" dojoAttachPoint=\"statusBarNode\">${_noFilterMsg}</span\r\n\t\t\t><span dojoType=\"dijit.form.Button\" class=\"dojoxGridFBarClearFilterBtn\" dojoAttachPoint=\"clearFilterButton\" \r\n\t\t\t\tlabel=\"${_filterBarClearBtnLabel}\" iconClass=\"dojoxGridFBarClearFilterBtnIcon\" showLabel=\"true\" \r\n\t\t\t\tdojoAttachEvent=\"onClick:_clearFilterDefDialog, onMouseEnter:_onEnterButton, onMouseLeave:_onLeaveButton, onMouseMove:_onMoveButton\"></span\r\n\t\t\t><span dojotype=\"dijit.form.Button\" class=\"dojoxGridFBarCloseBtn\" dojoAttachPoint=\"closeFilterBarButton\" \r\n\t\t\t\tlabel=\"${_closeFilterBarBtnLabel}\" iconClass=\"dojoxGridFBarCloseBtnIcon\" showLabel=\"false\" \r\n\t\t\t\tdojoAttachEvent=\"onClick:_closeFilterBar, onMouseEnter:_onEnterButton, onMouseLeave:_onLeaveButton, onMouseMove:_onMoveButton\"></span\r\n\t\t></span\r\n\t></td></tr\r\n></table>\r\n"),
+ 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 = dojo.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 = dojo.hitch(this, "showFilterBar");
+ g.toggleFilterBar = dojo.hitch(this, "toggleFilterBar");
+ g.isFilterBarShown = dojo.hitch(this, "isFilterBarShown");
+ },
+ postCreate: function(){
+ this.inherited(arguments);
+ if(!this.plugin.args.closeFilterbarButton){
+ dojo.style(this.closeFilterBarButton.domNode, "display", "none");
+ }
+ var _this = this,
+ g = this.plugin.grid,
+ old_func = this.oldGetHeaderHeight = dojo.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(dojo.hasClass(dojo.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() + dojo.marginBox(_this.domNode).h;
+ };
+ //Define an area to make focusManager handle all the navigation stuff
+ g.focus.addArea({
+ name: "filterbar",
+ onFocus: dojo.hitch(this, this._onFocusFilterBar, false),
+ onBlur: dojo.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 dojo.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(dojo.fx[toShow ? "wipeIn" : "wipeOut"](dojo.mixin({
+ "node": this.domNode,
+ "duration": defaultDuration
+ }, animArgs)));
+ var curHeight = g.views.views[0].domNode.offsetHeight;
+ var prop = {
+ "duration": defaultDuration,
+ "properties": {
+ "height": {
+ "end": dojo.hitch(this, function(){
+ var barHeight = this.domNode.scrollHeight;
+ if(dojo.isFF){
+ barHeight -= 2;
+ }
+ return toShow ? (curHeight - barHeight) : (curHeight + barHeight);
+ })
+ }
+ }
+ };
+ dojo.forEach(g.views.views, function(view){
+ anims.push(dojo.animateProperty(dojo.mixin({
+ "node": view.domNode
+ }, prop, animArgs)), dojo.animateProperty(dojo.mixin({
+ "node": view.scrollboxNode
+ }, prop, animArgs)));
+ });
+ anims.push(dojo.animateProperty(dojo.mixin({
+ "node": g.viewsNode
+ }, prop, animArgs)));
+ dojo.fx.combine(anims).play();
+ }else{
+ dojo.style(this.domNode, "display", toShow ? "" : "none");
+ g.update();
+ }
+ },
+ toggleFilterBar: function(useAnim, animArgs){
+ this.showFilterBar(!this.isFilterBarShown(), useAnim, animArgs);
+ },
+ getColumnIdx: function(/* int */coordX){
+ var headers = dojo.query("[role='columnheader']", this.plugin.grid.viewsHeaderNode);
+ var idx = -1;
+ for(var i = headers.length - 1; i >= 0; --i){
+ var coord = dojo.coords(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){
+ dojo.style(this.clearFilterButton.domNode, "display", toHide ? "none" : "");
+ },
+ _closeFilterBar: function(e){
+ _stopEvent(e);
+ var rulesCnt = this.plugin.filterDefDialog.getCriteria();
+ if(rulesCnt){
+ var handle = dojo.connect(this.plugin.filterDefDialog, "clearFilter", this, function(){
+ this.showFilterBar(false, true);
+ dojo.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;
+ dijit.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;
+ dojo.addClass(this.domNode,_focusClass);
+ if(!highlightOnly){
+ var hasFilter = dojo.style(this.clearFilterButton.domNode, "display") !== "none";
+ var hasCloseButton = dojo.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){
+ dijit.focus(this.defineFilterButton.focusNode);
+ }else if(this._focusPos === 1 && hasFilter){
+ dijit.focus(this.clearFilterButton.focusNode);
+ }else{
+ dijit.focus(this.closeFilterBarButton.focusNode);
+ }
+ }
+ _stopEvent(evt);
+ return true;
+ },
+ _onBlurFilterBar: function(evt, step){
+ if(this._isFocused){
+ this._isFocused = false;
+ dojo.removeClass(this.domNode,_focusClass);
+ this._clearStatusTipTimeout();
+ this._clearHeaderHighlight();
+ }
+ var toBlur = true;
+ if(step){
+ var buttonCount = 3;
+ if(dojo.style(this.closeFilterBarButton.domNode, "display") === "none"){
+ --buttonCount;
+ }
+ if(dojo.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 = dojo.string.substitute(p.nls["filterBarMsgHasFilterTemplate"], [filteredSize, originSize, itemsName]);
+ dojo.addClass(this.domNode, _filteredClass);
+ }else{
+ msg = dojo.string.substitute(p.nls["filterBarMsgNoFilterTemplate"], [originSize, itemsName]);
+ dojo.removeClass(this.domNode, _filteredClass);
+ }
+ this.statusBarNode.innerHTML = msg;
+ this._focusPos = 0;
+ },
+ _initAriaInfo: function(){
+ dijit.setWaiState(this.defineFilterButton.domNode, "label", this.plugin.nls["waiFilterBarDefButton"]);
+ dijit.setWaiState(this.clearFilterButton.domNode,"label", this.plugin.nls["waiFilterBarClearButton"]);
+ },
+ _isInColumn: function(/* int */mousePos_x, /* domNode */headerNode, /* int */colIndex){
+ var coord = dojo.coords(headerNode);
+ return mousePos_x >= coord.x && mousePos_x < coord.x + coord.w;
+ },
+ _setStatusTipTimeout: function(){
+ this._clearStatusTipTimeout();
+ if(!this._defPaneIsShown){
+ this._handle_statusTooltip = setTimeout(dojo.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){
+ dojo.removeClass(cell.getHeaderNode(), "dojoxGridCellOver");
+ }
+ cell = g.getCell(colIdx);
+ if(cell){
+ dojo.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-1.6/dojox/grid/enhanced/plugins/filter/FilterBar.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterBar.xd.js new file mode 100644 index 0000000..df88446 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterBar.xd.js @@ -0,0 +1,387 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.filter.FilterBar"],
+["require", "dijit.form.Button"],
+["require", "dojo.string"],
+["require", "dojo.fx"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterBar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterBar"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter.FilterBar");
+
+dojo.require("dijit.form.Button");
+dojo.require("dojo.string");
+dojo.require("dojo.fx");
+
+(function(){
+var _focusClass = "dojoxGridFBarHover",
+ _filteredClass = "dojoxGridFBarFiltered",
+ _stopEvent = function(evt){
+ try{
+ if(evt && evt.preventDefault){
+ dojo.stopEvent(evt);
+ }
+ }catch(e){}
+ };
+
+dojo.declare("dojox.grid.enhanced.plugins.filter.FilterBar",[dijit._Widget, dijit._Templated],{
+ // summary:
+ // The filter bar UI.
+ templateString: dojo.cache("dojox.grid", "enhanced/templates/FilterBar.html", "<table class=\"dojoxGridFBar\" border=\"0\" cellspacing=\"0\" dojoAttachEvent=\"onclick:_onClickFilterBar, onmouseenter:_onMouseEnter, onmouseleave:_onMouseLeave, onmousemove:_onMouseMove\"\r\n\t><tr><td class=\"dojoxGridFBarBtnTD\"\r\n\t\t><span dojoType=\"dijit.form.Button\" class=\"dojoxGridFBarBtn\" dojoAttachPoint=\"defineFilterButton\" label=\"...\" iconClass=\"dojoxGridFBarDefFilterBtnIcon\" showLabel=\"true\" dojoAttachEvent=\"onClick:_showFilterDefDialog, onMouseEnter:_onEnterButton, onMouseLeave:_onLeaveButton, onMouseMove:_onMoveButton\"></span\r\n\t></td><td class=\"dojoxGridFBarInfoTD\"\r\n\t\t><span class=\"dojoxGridFBarInner\"\r\n\t\t\t><span class=\"dojoxGridFBarStatus\" dojoAttachPoint=\"statusBarNode\">${_noFilterMsg}</span\r\n\t\t\t><span dojoType=\"dijit.form.Button\" class=\"dojoxGridFBarClearFilterBtn\" dojoAttachPoint=\"clearFilterButton\" \r\n\t\t\t\tlabel=\"${_filterBarClearBtnLabel}\" iconClass=\"dojoxGridFBarClearFilterBtnIcon\" showLabel=\"true\" \r\n\t\t\t\tdojoAttachEvent=\"onClick:_clearFilterDefDialog, onMouseEnter:_onEnterButton, onMouseLeave:_onLeaveButton, onMouseMove:_onMoveButton\"></span\r\n\t\t\t><span dojotype=\"dijit.form.Button\" class=\"dojoxGridFBarCloseBtn\" dojoAttachPoint=\"closeFilterBarButton\" \r\n\t\t\t\tlabel=\"${_closeFilterBarBtnLabel}\" iconClass=\"dojoxGridFBarCloseBtnIcon\" showLabel=\"false\" \r\n\t\t\t\tdojoAttachEvent=\"onClick:_closeFilterBar, onMouseEnter:_onEnterButton, onMouseLeave:_onLeaveButton, onMouseMove:_onMoveButton\"></span\r\n\t\t></span\r\n\t></td></tr\r\n></table>\r\n"),
+ 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 = dojo.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 = dojo.hitch(this, "showFilterBar");
+ g.toggleFilterBar = dojo.hitch(this, "toggleFilterBar");
+ g.isFilterBarShown = dojo.hitch(this, "isFilterBarShown");
+ },
+ postCreate: function(){
+ this.inherited(arguments);
+ if(!this.plugin.args.closeFilterbarButton){
+ dojo.style(this.closeFilterBarButton.domNode, "display", "none");
+ }
+ var _this = this,
+ g = this.plugin.grid,
+ old_func = this.oldGetHeaderHeight = dojo.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(dojo.hasClass(dojo.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() + dojo.marginBox(_this.domNode).h;
+ };
+ //Define an area to make focusManager handle all the navigation stuff
+ g.focus.addArea({
+ name: "filterbar",
+ onFocus: dojo.hitch(this, this._onFocusFilterBar, false),
+ onBlur: dojo.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 dojo.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(dojo.fx[toShow ? "wipeIn" : "wipeOut"](dojo.mixin({
+ "node": this.domNode,
+ "duration": defaultDuration
+ }, animArgs)));
+ var curHeight = g.views.views[0].domNode.offsetHeight;
+ var prop = {
+ "duration": defaultDuration,
+ "properties": {
+ "height": {
+ "end": dojo.hitch(this, function(){
+ var barHeight = this.domNode.scrollHeight;
+ if(dojo.isFF){
+ barHeight -= 2;
+ }
+ return toShow ? (curHeight - barHeight) : (curHeight + barHeight);
+ })
+ }
+ }
+ };
+ dojo.forEach(g.views.views, function(view){
+ anims.push(dojo.animateProperty(dojo.mixin({
+ "node": view.domNode
+ }, prop, animArgs)), dojo.animateProperty(dojo.mixin({
+ "node": view.scrollboxNode
+ }, prop, animArgs)));
+ });
+ anims.push(dojo.animateProperty(dojo.mixin({
+ "node": g.viewsNode
+ }, prop, animArgs)));
+ dojo.fx.combine(anims).play();
+ }else{
+ dojo.style(this.domNode, "display", toShow ? "" : "none");
+ g.update();
+ }
+ },
+ toggleFilterBar: function(useAnim, animArgs){
+ this.showFilterBar(!this.isFilterBarShown(), useAnim, animArgs);
+ },
+ getColumnIdx: function(/* int */coordX){
+ var headers = dojo.query("[role='columnheader']", this.plugin.grid.viewsHeaderNode);
+ var idx = -1;
+ for(var i = headers.length - 1; i >= 0; --i){
+ var coord = dojo.coords(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){
+ dojo.style(this.clearFilterButton.domNode, "display", toHide ? "none" : "");
+ },
+ _closeFilterBar: function(e){
+ _stopEvent(e);
+ var rulesCnt = this.plugin.filterDefDialog.getCriteria();
+ if(rulesCnt){
+ var handle = dojo.connect(this.plugin.filterDefDialog, "clearFilter", this, function(){
+ this.showFilterBar(false, true);
+ dojo.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;
+ dijit.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;
+ dojo.addClass(this.domNode,_focusClass);
+ if(!highlightOnly){
+ var hasFilter = dojo.style(this.clearFilterButton.domNode, "display") !== "none";
+ var hasCloseButton = dojo.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){
+ dijit.focus(this.defineFilterButton.focusNode);
+ }else if(this._focusPos === 1 && hasFilter){
+ dijit.focus(this.clearFilterButton.focusNode);
+ }else{
+ dijit.focus(this.closeFilterBarButton.focusNode);
+ }
+ }
+ _stopEvent(evt);
+ return true;
+ },
+ _onBlurFilterBar: function(evt, step){
+ if(this._isFocused){
+ this._isFocused = false;
+ dojo.removeClass(this.domNode,_focusClass);
+ this._clearStatusTipTimeout();
+ this._clearHeaderHighlight();
+ }
+ var toBlur = true;
+ if(step){
+ var buttonCount = 3;
+ if(dojo.style(this.closeFilterBarButton.domNode, "display") === "none"){
+ --buttonCount;
+ }
+ if(dojo.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 = dojo.string.substitute(p.nls["filterBarMsgHasFilterTemplate"], [filteredSize, originSize, itemsName]);
+ dojo.addClass(this.domNode, _filteredClass);
+ }else{
+ msg = dojo.string.substitute(p.nls["filterBarMsgNoFilterTemplate"], [originSize, itemsName]);
+ dojo.removeClass(this.domNode, _filteredClass);
+ }
+ this.statusBarNode.innerHTML = msg;
+ this._focusPos = 0;
+ },
+ _initAriaInfo: function(){
+ dijit.setWaiState(this.defineFilterButton.domNode, "label", this.plugin.nls["waiFilterBarDefButton"]);
+ dijit.setWaiState(this.clearFilterButton.domNode,"label", this.plugin.nls["waiFilterBarClearButton"]);
+ },
+ _isInColumn: function(/* int */mousePos_x, /* domNode */headerNode, /* int */colIndex){
+ var coord = dojo.coords(headerNode);
+ return mousePos_x >= coord.x && mousePos_x < coord.x + coord.w;
+ },
+ _setStatusTipTimeout: function(){
+ this._clearStatusTipTimeout();
+ if(!this._defPaneIsShown){
+ this._handle_statusTooltip = setTimeout(dojo.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){
+ dojo.removeClass(cell.getHeaderNode(), "dojoxGridCellOver");
+ }
+ cell = g.getCell(colIdx);
+ if(cell){
+ dojo.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-1.6/dojox/grid/enhanced/plugins/filter/FilterBuilder.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterBuilder.js new file mode 100644 index 0000000..7231252 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterBuilder.js @@ -0,0 +1,89 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterBuilder"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterBuilder"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter.FilterBuilder");
+dojo.require("dojox.grid.enhanced.plugins.filter._FilterExpr");
+
+(function(){
+var fns = dojox.grid.enhanced.plugins.filter,
+ bdr = function(opCls){
+ return dojo.partial(function(cls,operands){
+ return new fns[cls](operands);
+ },opCls);
+ },
+ bdr_not = function(opCls){
+ return dojo.partial(function(cls,operands){
+ return new fns.LogicNOT(new fns[cls](operands));
+ },opCls);
+ };
+dojo.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()](dojo.map(def.data, this.buildExpression, this));
+ }else{
+ var args = dojo.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 fns.LogicALL(
+ new fns.LargerThanOrEqualTo(operands.slice(0,2)),
+ new fns.LessThanOrEqualTo(operands[0], operands[2])
+ );
+ },
+ "logicany": bdr("LogicANY"),
+ "logicall": bdr("LogicALL")
+ },
+ supportedTypes: {
+ "number": fns.NumberExpr,
+ "string": fns.StringExpr,
+ "boolean": fns.BooleanExpr,
+ "date": fns.DateExpr,
+ "time": fns.TimeExpr
+ },
+ defaultArgs: {
+ "boolean": {
+ "falseValue": "false",
+ "convert": function(dataValue, args){
+ var falseValue = args.falseValue;
+ var trueValue = args.trueValue;
+ if(dojo.isString(dataValue)){
+ if(trueValue && dataValue.toLowerCase() == trueValue){
+ return true;
+ }
+ if(falseValue && dataValue.toLowerCase() == falseValue){
+ return false;
+ }
+ }
+ return !!dataValue;
+ }
+ }
+ }
+});
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterBuilder.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterBuilder.xd.js new file mode 100644 index 0000000..c8c8cdb --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterBuilder.xd.js @@ -0,0 +1,94 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.filter.FilterBuilder"],
+["require", "dojox.grid.enhanced.plugins.filter._FilterExpr"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterBuilder"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterBuilder"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter.FilterBuilder");
+dojo.require("dojox.grid.enhanced.plugins.filter._FilterExpr");
+
+(function(){
+var fns = dojox.grid.enhanced.plugins.filter,
+ bdr = function(opCls){
+ return dojo.partial(function(cls,operands){
+ return new fns[cls](operands);
+ },opCls);
+ },
+ bdr_not = function(opCls){
+ return dojo.partial(function(cls,operands){
+ return new fns.LogicNOT(new fns[cls](operands));
+ },opCls);
+ };
+dojo.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()](dojo.map(def.data, this.buildExpression, this));
+ }else{
+ var args = dojo.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 fns.LogicALL(
+ new fns.LargerThanOrEqualTo(operands.slice(0,2)),
+ new fns.LessThanOrEqualTo(operands[0], operands[2])
+ );
+ },
+ "logicany": bdr("LogicANY"),
+ "logicall": bdr("LogicALL")
+ },
+ supportedTypes: {
+ "number": fns.NumberExpr,
+ "string": fns.StringExpr,
+ "boolean": fns.BooleanExpr,
+ "date": fns.DateExpr,
+ "time": fns.TimeExpr
+ },
+ defaultArgs: {
+ "boolean": {
+ "falseValue": "false",
+ "convert": function(dataValue, args){
+ var falseValue = args.falseValue;
+ var trueValue = args.trueValue;
+ if(dojo.isString(dataValue)){
+ if(trueValue && dataValue.toLowerCase() == trueValue){
+ return true;
+ }
+ if(falseValue && dataValue.toLowerCase() == falseValue){
+ return false;
+ }
+ }
+ return !!dataValue;
+ }
+ }
+ }
+});
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterDefDialog.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterDefDialog.js new file mode 100644 index 0000000..40880ac --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterDefDialog.js @@ -0,0 +1,1236 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterDefDialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterDefDialog"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter.FilterDefDialog");
+
+dojo.require("dijit.dijit");
+dojo.require("dijit.Tooltip");
+dojo.require("dojox.grid.enhanced.plugins.Dialog");
+dojo.require("dijit.form.ComboBox");
+dojo.require("dijit.form.Select");
+dojo.require("dijit.form.TextBox");
+dojo.require("dijit.form.CheckBox");
+dojo.require("dijit.form.NumberTextBox");
+dojo.require("dijit.form.DateTextBox");
+dojo.require("dijit.form.TimeTextBox");
+dojo.require("dijit.form.Button");
+dojo.require("dijit.layout.AccordionContainer");
+dojo.require("dijit.layout.ContentPane");
+dojo.require("dojo.date.locale");
+dojo.require("dojo.string");
+dojo.require("dojox.grid.enhanced.plugins.filter.FilterBuilder");
+dojo.require("dojox.grid.cells.dijit");
+dojo.require("dojox.html.ellipsis");
+dojo.require("dojox.html.metrics");
+dojo.require("dojo.window");
+
+(function(){
+var fns = dojox.grid.enhanced.plugins.filter,
+ _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
+ };
+dojo.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 fns.FilterBuilder();
+ this._setupData();
+ this._cboxes = [];
+ this.defaultType = plugin.args.defaultType || "string";
+
+ (this.filterDefPane = new fns.FilterDefPane({
+ "dlg": this
+ })).startup();
+ (this._defPane = new dojox.grid.enhanced.plugins.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", dojo.hitch(this, "_onSetFilter"));
+ plugin.grid.setFilter = dojo.hitch(this, "setFilter");
+ plugin.grid.getFilter = dojo.hitch(this, "getFilter");
+ plugin.grid.getFilterRelation = dojo.hitch(this, function(){
+ return this._relOpCls;
+ });
+
+ plugin.connect(plugin.grid.layout, "moveColumn", dojo.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;
+ dojo.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: dijit.form.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: dijit.form.TextBox,
+ ac: fns.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: dijit.form.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: dijit.form.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: fns.BooleanValueBox
+ },
+ conditions: [
+ {label: nls.conditionIs, value: "equalto", selected: true},
+ {label: nls.conditionIsEmpty, value: "isempty"}
+ ]
+ }
+ };
+ },
+ setFilter: function(rules, ruleRelation){
+ rules = rules || [];
+ if(!dojo.isArray(rules)){
+ rules = [rules];
+ }
+ var func = function(){
+ if(rules.length){
+ this._savedCriterias = dojo.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 = dojo.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 = dojo.connect(this, "clearFilter", this, function(){
+ dojo.disconnect(handle);
+ this._clearWithoutRefresh = false;
+ func.apply(this);
+ });
+ this.onClearFilter();
+ }else{
+ func.apply(this);
+ }
+ },
+ getFilter: function(){
+ return dojo.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 fns.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(dojo.isIE <= 6 && !this.__alreadyResizedForIE6){
+ var size = dojo.position(cc.domNode);
+ size.w -= dojox.html.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 = dojo.indexOf(cbs, cc.selectedChildWidget.content);
+ if(dojo.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 && dojo.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 fns.CriteriaBox){
+ cbox = cnt;
+ cnt = 1;
+ start = end = dojo.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 dojo.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 = dojo.filter(this.plugin.grid.layout.cells, function(cell){
+ return !(cell.filterable === false || cell.hidden);
+ });
+ return {
+ "op": "logicany",
+ "data": dojo.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 = [dojo.mixin({"data": this.plugin.args.isServerSide ? colName : cell}, obj)];
+ obj.isColumn = false;
+ if(condition == "range"){
+ operands.push(dojo.mixin({"data": value.start}, obj),
+ dojo.mixin({"data": value.end}, obj));
+ }else if(condition != "isempty"){
+ operands.push(dojo.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.
+ 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 > 1){
+ 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);
+ dojo.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(!dojo.isFF){
+ var elems = dijit._getTabNavigable(dojo.byId(cbox.domNode));
+ dijit.focus(elems.lowest || elems.first);
+ }else{
+ var dp = this._defPane;
+ dp._getFocusItems(dp.domNode);
+ dijit.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,
+ columnChanged = this.curColIdx != colIndex;
+ this.curColIdx = colIndex;
+ if(!sc){
+ if(cbs.length === 0){
+ this.addCriteriaBoxes(1);
+ }else if(columnChanged){
+ 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;
+ this.addCriteriaBoxes(sc.length - cbs.length);
+ this.removeCriteriaBoxes(cbs.length - sc.length);
+ this.filterDefPane._clearFilterBtn.set("disabled", false);
+ if(needNewCBox){
+ dojo.forEach(sc, function(c, i){
+ var handle = dojo.connect(this, "onRendered", function(cbox){
+ if(cbox == cbs[i]){
+ dojo.disconnect(handle);
+ cbox.load(c);
+ }
+ });
+ }, this);
+ }else{
+ for(i = 0; i < sc.length; ++i){
+ cbs[i].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 dojo.filter(dojo.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 dojo.filter(this._cboxes, function(cbox){
+ return !cbox.isEmpty();
+ }).length > 0;
+ },
+ _closeDlgAndUpdateGrid: function(){
+ this.closeDialog();
+ var g = this.plugin.grid;
+ g.showMessage(g.loadingMessage);
+ setTimeout(dojo.hitch(g, g._refresh), this._defPane.duration + 10);
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter.FilterDefPane",[dijit._Widget,dijit._Templated],{
+ templateString: dojo.cache("dojox.grid", "enhanced/templates/FilterDefPane.html", "<div class=\"dojoxGridFDPane\">\r\n\t<div class=\"dojoxGridFDPaneRelation\">${_relMsgFront}\r\n\t<span class=\"dojoxGridFDPaneModes\" dojoAttachPoint=\"criteriaModeNode\">\r\n\t\t<select dojoAttachPoint=\"_relSelect\" dojoType=\"dijit.form.Select\" dojoAttachEvent=\"onChange: _onRelSelectChange\">\r\n\t\t\t<option value=\"0\">${_relAll}</option>\r\n\t\t\t<option value=\"1\">${_relAny}</option>\r\n\t\t</select>\r\n\t</span>\r\n\t${_relMsgTail}\r\n\t</div>\r\n\t<div dojoAttachPoint=\"criteriaPane\" class=\"dojoxGridFDPaneRulePane\"></div>\r\n\t<div dojoAttachPoint=\"_addCBoxBtn\" dojoType=\"dijit.form.Button\" \r\n\t\tclass=\"dojoxGridFDPaneAddCBoxBtn\" iconClass=\"dojoxGridFDPaneAddCBoxBtnIcon\"\r\n\t\tdojoAttachEvent=\"onClick:_onAddCBox\" label=\"${_addRuleBtnLabel}\" showLabel=\"false\">\r\n\t</div>\r\n\t<div class=\"dojoxGridFDPaneBtns\" dojoAttachPoint=\"buttonsPane\">\r\n\t\t<span dojoAttachPoint=\"_cancelBtn\" dojoType=\"dijit.form.Button\" \r\n\t\t\tdojoAttachEvent=\"onClick:_onCancel\" label=\"${_cancelBtnLabel}\">\r\n\t\t</span>\r\n\t\t<span dojoAttachPoint=\"_clearFilterBtn\" dojoType=\"dijit.form.Button\" \r\n\t\t\tdojoAttachEvent=\"onClick:_onClearFilter\" label=\"${_clearBtnLabel}\" disabled=\"true\">\r\n\t\t</span>\r\n\t\t<span dojoAttachPoint=\"_filterBtn\" dojoType=\"dijit.form.Button\" \r\n\t\t\tdojoAttachEvent=\"onClick:_onFilter\" label=\"${_filterBtnLabel}\" disabled=\"true\">\r\n\t\t</span>\r\n\t</div>\r\n</div>\r\n"),
+ 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 fns.AccordionContainer({
+ 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;
+ dijit.setWaiState(this._relSelect.domNode, "label", nls.waiRelAll);
+ dijit.setWaiState(this._addCBoxBtn.domNode, "label", nls.waiAddRuleButton);
+ dijit.setWaiState(this._cancelBtn.domNode, "label", nls.waiCancelButton);
+ dijit.setWaiState(this._clearFilterBtn.domNode, "label", nls.waiClearButton);
+ dijit.setWaiState(this._filterBtn.domNode, "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";
+ dijit.setWaiState(this._relSelect.domNode,"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 == dojo.keys.ENTER){
+ this.dlg.onFilter();
+ }
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter.CriteriaBox",[dijit._Widget,dijit._Templated],{
+ templateString: dojo.cache("dojox.grid", "enhanced/templates/CriteriaBox.html", "<div class=\"dojoxGridFCBox\">\r\n\t<div class=\"dojoxGridFCBoxSelCol\" dojoAttachPoint=\"selColNode\">\r\n\t\t<span class=\"dojoxGridFCBoxField\">${_colSelectLabel}</span>\r\n\t\t<select dojoAttachPoint=\"_colSelect\" dojoType=\"dijit.form.Select\" \r\n\t\t\tclass=\"dojoxGridFCBoxColSelect\"\r\n\t\t\tdojoAttachEvent=\"onChange:_onChangeColumn\">\r\n\t\t</select>\r\n\t</div>\r\n\t<div class=\"dojoxGridFCBoxCondition\" dojoAttachPoint=\"condNode\">\r\n\t\t<span class=\"dojoxGridFCBoxField\">${_condSelectLabel}</span>\r\n\t\t<select dojoAttachPoint=\"_condSelect\" dojoType=\"dijit.form.Select\" \r\n\t\t\tclass=\"dojoxGridFCBoxCondSelect\"\r\n\t\t\tdojoAttachEvent=\"onChange:_onChangeCondition\">\r\n\t\t</select>\r\n\t\t<div class=\"dojoxGridFCBoxCondSelectAlt\" dojoAttachPoint=\"_condSelectAlt\" style=\"display:none;\"></div>\r\n\t</div>\r\n\t<div class=\"dojoxGridFCBoxValue\" dojoAttachPoint=\"valueNode\">\r\n\t\t<span class=\"dojoxGridFCBoxField\">${_valueBoxLabel}</span>\r\n\t</div>\r\n</div>\r\n"),
+ 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 dojo.map(dojo.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;
+ dojo.style(sel.domNode, "display", "none");
+ dojo.style(alt, "display", "");
+ }else{
+ dojo.style(sel.domNode, "display", "");
+ dojo.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(dojo.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 = dojo.hitch(arg.cbox, "_checkValidCriteria");
+ return new cls(dojo.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 = dojo.hitch(arg.cbox, "_checkValidCriteria");
+ dojo.mixin(arg,{
+ tabIndex: _tabIdxes.valueBox,
+ onKeyPress: func,
+ onChange: func
+ });
+ var div = dojo.create("div", {"class": "dojoxGridFCBoxValueBox"}),
+ start = new cls(arg),
+ txt = dojo.create("span", {"class": "dojoxGridFCBoxRangeValueTxt", "innerHTML": this.plugin.nls.rangeTo}),
+ end = new cls(arg);
+ dojo.addClass(start.domNode, "dojoxGridFCBoxStartValue");
+ dojo.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(dojo.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;
+ 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(dojo.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 = dojo.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,
+ " <span class='dojoxGridRuleTitleCondition'>",
+ condition,
+ "</span> ",
+ value
+ );
+ node.title = [column, " ", condition, " ", value].join('');
+ }
+ node.innerHTML = title.join('');
+ if(dojo.isMoz){
+ var tt = dojo.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 = dojo.string.substitute, nls = this.plugin.nls;
+ dijit.setWaiState(this._colSelect.domNode,"label", dss(nls.waiColumnSelectTemplate, [idx]));
+ dijit.setWaiState(this._condSelect.domNode,"label", dss(nls.waiConditionSelectTemplate, [idx]));
+ dijit.setWaiState(this._pane._removeCBoxBtn.domNode,"label", dss(nls.waiRemoveRuleButtonTemplate, [idx]));
+ this._index = idx;
+ },
+ _getUsableConditions: function(type){
+ var conditions = 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(!dojo.isArray(typeDisabledConds)){
+ typeDisabledConds = [];
+ }
+ if(!dojo.isArray(colDisabledConds)){
+ colDisabledConds = [];
+ }
+ var arr = typeDisabledConds.concat(colDisabledConds);
+ if(arr.length){
+ var disabledConds = {};
+ dojo.forEach(arr, function(c){
+ if(dojo.isString(c)){
+ disabledConds[c.toLowerCase()] = true;
+ }
+ });
+ return dojo.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.
+ dijit.setWaiState(this._curValueBox.domNode, "label", dojo.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)){
+ dojo.mixin(res, {
+ store: g.store,
+ searchAttr: cell.field || cell.name,
+ fetchProperties: {
+ sort: [{"attribute": cell.field || cell.name}]
+ }
+ });
+ }
+ }else if(type == "boolean"){
+ dojo.mixin(res, this.dlg.builder.defaultArgs["boolean"]);
+ }
+ if(cell && cell.dataTypeArgs){
+ dojo.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 = dojo.date.locale.format;
+ if(cond == "range"){
+ return dojo.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";
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter.AccordionContainer", dijit.layout.AccordionContainer, {
+ nls: null,
+ addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
+ var pane = arguments[0] = child._pane = new dijit.layout.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){
+ dojo.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);
+ dojo.forEach(this.getChildren(), this._setupTitleDom);
+ },
+ startup: function(){
+ if(this._started){
+ return;
+ }
+ this.inherited(arguments);
+ if(parseInt(dojo.isIE, 10) == 7){
+ //IE7 will fire a lot of "onresize" event during initialization.
+ dojo.some(this._connects, function(cnnt){
+ if(cnnt[0][1] == "onresize"){
+ this.disconnect(cnnt);
+ return true;
+ }
+ }, this);
+ }
+ dojo.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 = dojo.keys, c = e.charOrCode, ltr = dojo._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();
+ }
+ dojo.stopEvent(e);
+ dojo.window.scrollIntoView(this.selectedChildWidget._buttonWidget.domNode.parentNode);
+ if(dojo.isIE){
+ //IE will not show focus indicator if tabIndex is -1
+ this.selectedChildWidget._removeCBoxBtn.focusNode.setAttribute("tabIndex", this._focusOnRemoveBtn ? _tabIdxes.accordionTitle : -1);
+ }
+ dijit.focus(this.selectedChildWidget[this._focusOnRemoveBtn ? "_removeCBoxBtn" : "_buttonWidget"].focusNode);
+ },
+ _modifyChild: function(child, isFirst){
+ if(!child || !this._started){
+ return;
+ }
+ dojo.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 dijit.form.Button({
+ label: this.nls.removeRuleButton,
+ showLabel: false,
+ iconClass: "dojoxGridFCBoxRemoveCBoxBtnIcon",
+ tabIndex: _tabIdxes.removeCBoxBtn,
+ onClick: dojo.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);
+ dojo.style(child._removeCBoxBtn.domNode, "display", "none");
+ }else{
+ for(i = 0; i < children.length; ++i){
+ if(children[i]._removeCBoxBtn){
+ dojo.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 = dojo.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 = dojo.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 = dojo.contentBox(child._buttonWidget.titleNode).w;
+ if(dojo.isIE < 8){ w -= 8; }
+ dojo.style(child._buttonWidget.titleTextNode, "width", w + "px");
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter.UniqueComboBox", dijit.form.ComboBox, {
+ _openResultList: function(results){
+ var cache = {}, s = this.store, colName = this.searchAttr;
+ arguments[0] = dojo.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 === dojo.keys.ENTER && this._opened){
+ dojo.stopEvent(evt);
+ }
+ this.inherited(arguments);
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter.BooleanValueBox", [dijit._Widget, dijit._Templated], {
+ templateString: dojo.cache("dojox.grid", "enhanced/templates/FilterBoolValueBox.html", "<div class=\"dojoxGridBoolValueBox\">\r\n\t<div class=\"dojoxGridTrueBox\">\r\n\t\t<input dojoType=\"dijit.form.RadioButton\" type='radio' name='a1' id='${_baseId}_rbTrue' checked=\"true\" \r\n\t\t\tdojoAttachPoint=\"rbTrue\" dojoAttachEvent=\"onChange: onChange\"/>\r\n\t\t<div class=\"dojoxGridTrueLabel\" for='${_baseId}_rbTrue'>${_lblTrue}</div>\r\n\t</div>\r\n\t<div class=\"dojoxGridFalseBox\">\r\n\t\t<input dojoType=\"dijit.form.RadioButton\" dojoAttachPoint=\"rbFalse\" type='radio' name='a1' id='${_baseId}_rbFalse'/>\r\n\t\t<div class=\"dojoxGridTrueLabel\" for='${_baseId}_rbFalse'>${_lblFalse}</div>\r\n\t</div>\r\n</div>\r\n"),
+ 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);
+ }
+ }
+});
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterDefDialog.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterDefDialog.xd.js new file mode 100644 index 0000000..ba827a8 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterDefDialog.xd.js @@ -0,0 +1,1260 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.filter.FilterDefDialog"],
+["require", "dijit.dijit"],
+["require", "dijit.Tooltip"],
+["require", "dojox.grid.enhanced.plugins.Dialog"],
+["require", "dijit.form.ComboBox"],
+["require", "dijit.form.Select"],
+["require", "dijit.form.TextBox"],
+["require", "dijit.form.CheckBox"],
+["require", "dijit.form.NumberTextBox"],
+["require", "dijit.form.DateTextBox"],
+["require", "dijit.form.TimeTextBox"],
+["require", "dijit.form.Button"],
+["require", "dijit.layout.AccordionContainer"],
+["require", "dijit.layout.ContentPane"],
+["require", "dojo.date.locale"],
+["require", "dojo.string"],
+["require", "dojox.grid.enhanced.plugins.filter.FilterBuilder"],
+["require", "dojox.grid.cells.dijit"],
+["require", "dojox.html.ellipsis"],
+["require", "dojox.html.metrics"],
+["require", "dojo.window"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterDefDialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterDefDialog"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter.FilterDefDialog");
+
+dojo.require("dijit.dijit");
+dojo.require("dijit.Tooltip");
+dojo.require("dojox.grid.enhanced.plugins.Dialog");
+dojo.require("dijit.form.ComboBox");
+dojo.require("dijit.form.Select");
+dojo.require("dijit.form.TextBox");
+dojo.require("dijit.form.CheckBox");
+dojo.require("dijit.form.NumberTextBox");
+dojo.require("dijit.form.DateTextBox");
+dojo.require("dijit.form.TimeTextBox");
+dojo.require("dijit.form.Button");
+dojo.require("dijit.layout.AccordionContainer");
+dojo.require("dijit.layout.ContentPane");
+dojo.require("dojo.date.locale");
+dojo.require("dojo.string");
+dojo.require("dojox.grid.enhanced.plugins.filter.FilterBuilder");
+dojo.require("dojox.grid.cells.dijit");
+dojo.require("dojox.html.ellipsis");
+dojo.require("dojox.html.metrics");
+dojo.require("dojo.window");
+
+(function(){
+var fns = dojox.grid.enhanced.plugins.filter,
+ _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
+ };
+dojo.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 fns.FilterBuilder();
+ this._setupData();
+ this._cboxes = [];
+ this.defaultType = plugin.args.defaultType || "string";
+
+ (this.filterDefPane = new fns.FilterDefPane({
+ "dlg": this
+ })).startup();
+ (this._defPane = new dojox.grid.enhanced.plugins.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", dojo.hitch(this, "_onSetFilter"));
+ plugin.grid.setFilter = dojo.hitch(this, "setFilter");
+ plugin.grid.getFilter = dojo.hitch(this, "getFilter");
+ plugin.grid.getFilterRelation = dojo.hitch(this, function(){
+ return this._relOpCls;
+ });
+
+ plugin.connect(plugin.grid.layout, "moveColumn", dojo.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;
+ dojo.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: dijit.form.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: dijit.form.TextBox,
+ ac: fns.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: dijit.form.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: dijit.form.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: fns.BooleanValueBox
+ },
+ conditions: [
+ {label: nls.conditionIs, value: "equalto", selected: true},
+ {label: nls.conditionIsEmpty, value: "isempty"}
+ ]
+ }
+ };
+ },
+ setFilter: function(rules, ruleRelation){
+ rules = rules || [];
+ if(!dojo.isArray(rules)){
+ rules = [rules];
+ }
+ var func = function(){
+ if(rules.length){
+ this._savedCriterias = dojo.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 = dojo.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 = dojo.connect(this, "clearFilter", this, function(){
+ dojo.disconnect(handle);
+ this._clearWithoutRefresh = false;
+ func.apply(this);
+ });
+ this.onClearFilter();
+ }else{
+ func.apply(this);
+ }
+ },
+ getFilter: function(){
+ return dojo.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 fns.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(dojo.isIE <= 6 && !this.__alreadyResizedForIE6){
+ var size = dojo.position(cc.domNode);
+ size.w -= dojox.html.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 = dojo.indexOf(cbs, cc.selectedChildWidget.content);
+ if(dojo.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 && dojo.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 fns.CriteriaBox){
+ cbox = cnt;
+ cnt = 1;
+ start = end = dojo.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 dojo.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 = dojo.filter(this.plugin.grid.layout.cells, function(cell){
+ return !(cell.filterable === false || cell.hidden);
+ });
+ return {
+ "op": "logicany",
+ "data": dojo.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 = [dojo.mixin({"data": this.plugin.args.isServerSide ? colName : cell}, obj)];
+ obj.isColumn = false;
+ if(condition == "range"){
+ operands.push(dojo.mixin({"data": value.start}, obj),
+ dojo.mixin({"data": value.end}, obj));
+ }else if(condition != "isempty"){
+ operands.push(dojo.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.
+ 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 > 1){
+ 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);
+ dojo.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(!dojo.isFF){
+ var elems = dijit._getTabNavigable(dojo.byId(cbox.domNode));
+ dijit.focus(elems.lowest || elems.first);
+ }else{
+ var dp = this._defPane;
+ dp._getFocusItems(dp.domNode);
+ dijit.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,
+ columnChanged = this.curColIdx != colIndex;
+ this.curColIdx = colIndex;
+ if(!sc){
+ if(cbs.length === 0){
+ this.addCriteriaBoxes(1);
+ }else if(columnChanged){
+ 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;
+ this.addCriteriaBoxes(sc.length - cbs.length);
+ this.removeCriteriaBoxes(cbs.length - sc.length);
+ this.filterDefPane._clearFilterBtn.set("disabled", false);
+ if(needNewCBox){
+ dojo.forEach(sc, function(c, i){
+ var handle = dojo.connect(this, "onRendered", function(cbox){
+ if(cbox == cbs[i]){
+ dojo.disconnect(handle);
+ cbox.load(c);
+ }
+ });
+ }, this);
+ }else{
+ for(i = 0; i < sc.length; ++i){
+ cbs[i].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 dojo.filter(dojo.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 dojo.filter(this._cboxes, function(cbox){
+ return !cbox.isEmpty();
+ }).length > 0;
+ },
+ _closeDlgAndUpdateGrid: function(){
+ this.closeDialog();
+ var g = this.plugin.grid;
+ g.showMessage(g.loadingMessage);
+ setTimeout(dojo.hitch(g, g._refresh), this._defPane.duration + 10);
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter.FilterDefPane",[dijit._Widget,dijit._Templated],{
+ templateString: dojo.cache("dojox.grid", "enhanced/templates/FilterDefPane.html", "<div class=\"dojoxGridFDPane\">\r\n\t<div class=\"dojoxGridFDPaneRelation\">${_relMsgFront}\r\n\t<span class=\"dojoxGridFDPaneModes\" dojoAttachPoint=\"criteriaModeNode\">\r\n\t\t<select dojoAttachPoint=\"_relSelect\" dojoType=\"dijit.form.Select\" dojoAttachEvent=\"onChange: _onRelSelectChange\">\r\n\t\t\t<option value=\"0\">${_relAll}</option>\r\n\t\t\t<option value=\"1\">${_relAny}</option>\r\n\t\t</select>\r\n\t</span>\r\n\t${_relMsgTail}\r\n\t</div>\r\n\t<div dojoAttachPoint=\"criteriaPane\" class=\"dojoxGridFDPaneRulePane\"></div>\r\n\t<div dojoAttachPoint=\"_addCBoxBtn\" dojoType=\"dijit.form.Button\" \r\n\t\tclass=\"dojoxGridFDPaneAddCBoxBtn\" iconClass=\"dojoxGridFDPaneAddCBoxBtnIcon\"\r\n\t\tdojoAttachEvent=\"onClick:_onAddCBox\" label=\"${_addRuleBtnLabel}\" showLabel=\"false\">\r\n\t</div>\r\n\t<div class=\"dojoxGridFDPaneBtns\" dojoAttachPoint=\"buttonsPane\">\r\n\t\t<span dojoAttachPoint=\"_cancelBtn\" dojoType=\"dijit.form.Button\" \r\n\t\t\tdojoAttachEvent=\"onClick:_onCancel\" label=\"${_cancelBtnLabel}\">\r\n\t\t</span>\r\n\t\t<span dojoAttachPoint=\"_clearFilterBtn\" dojoType=\"dijit.form.Button\" \r\n\t\t\tdojoAttachEvent=\"onClick:_onClearFilter\" label=\"${_clearBtnLabel}\" disabled=\"true\">\r\n\t\t</span>\r\n\t\t<span dojoAttachPoint=\"_filterBtn\" dojoType=\"dijit.form.Button\" \r\n\t\t\tdojoAttachEvent=\"onClick:_onFilter\" label=\"${_filterBtnLabel}\" disabled=\"true\">\r\n\t\t</span>\r\n\t</div>\r\n</div>\r\n"),
+ 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 fns.AccordionContainer({
+ 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;
+ dijit.setWaiState(this._relSelect.domNode, "label", nls.waiRelAll);
+ dijit.setWaiState(this._addCBoxBtn.domNode, "label", nls.waiAddRuleButton);
+ dijit.setWaiState(this._cancelBtn.domNode, "label", nls.waiCancelButton);
+ dijit.setWaiState(this._clearFilterBtn.domNode, "label", nls.waiClearButton);
+ dijit.setWaiState(this._filterBtn.domNode, "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";
+ dijit.setWaiState(this._relSelect.domNode,"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 == dojo.keys.ENTER){
+ this.dlg.onFilter();
+ }
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter.CriteriaBox",[dijit._Widget,dijit._Templated],{
+ templateString: dojo.cache("dojox.grid", "enhanced/templates/CriteriaBox.html", "<div class=\"dojoxGridFCBox\">\r\n\t<div class=\"dojoxGridFCBoxSelCol\" dojoAttachPoint=\"selColNode\">\r\n\t\t<span class=\"dojoxGridFCBoxField\">${_colSelectLabel}</span>\r\n\t\t<select dojoAttachPoint=\"_colSelect\" dojoType=\"dijit.form.Select\" \r\n\t\t\tclass=\"dojoxGridFCBoxColSelect\"\r\n\t\t\tdojoAttachEvent=\"onChange:_onChangeColumn\">\r\n\t\t</select>\r\n\t</div>\r\n\t<div class=\"dojoxGridFCBoxCondition\" dojoAttachPoint=\"condNode\">\r\n\t\t<span class=\"dojoxGridFCBoxField\">${_condSelectLabel}</span>\r\n\t\t<select dojoAttachPoint=\"_condSelect\" dojoType=\"dijit.form.Select\" \r\n\t\t\tclass=\"dojoxGridFCBoxCondSelect\"\r\n\t\t\tdojoAttachEvent=\"onChange:_onChangeCondition\">\r\n\t\t</select>\r\n\t\t<div class=\"dojoxGridFCBoxCondSelectAlt\" dojoAttachPoint=\"_condSelectAlt\" style=\"display:none;\"></div>\r\n\t</div>\r\n\t<div class=\"dojoxGridFCBoxValue\" dojoAttachPoint=\"valueNode\">\r\n\t\t<span class=\"dojoxGridFCBoxField\">${_valueBoxLabel}</span>\r\n\t</div>\r\n</div>\r\n"),
+ 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 dojo.map(dojo.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;
+ dojo.style(sel.domNode, "display", "none");
+ dojo.style(alt, "display", "");
+ }else{
+ dojo.style(sel.domNode, "display", "");
+ dojo.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(dojo.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 = dojo.hitch(arg.cbox, "_checkValidCriteria");
+ return new cls(dojo.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 = dojo.hitch(arg.cbox, "_checkValidCriteria");
+ dojo.mixin(arg,{
+ tabIndex: _tabIdxes.valueBox,
+ onKeyPress: func,
+ onChange: func
+ });
+ var div = dojo.create("div", {"class": "dojoxGridFCBoxValueBox"}),
+ start = new cls(arg),
+ txt = dojo.create("span", {"class": "dojoxGridFCBoxRangeValueTxt", "innerHTML": this.plugin.nls.rangeTo}),
+ end = new cls(arg);
+ dojo.addClass(start.domNode, "dojoxGridFCBoxStartValue");
+ dojo.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(dojo.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;
+ 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(dojo.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 = dojo.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,
+ " <span class='dojoxGridRuleTitleCondition'>",
+ condition,
+ "</span> ",
+ value
+ );
+ node.title = [column, " ", condition, " ", value].join('');
+ }
+ node.innerHTML = title.join('');
+ if(dojo.isMoz){
+ var tt = dojo.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 = dojo.string.substitute, nls = this.plugin.nls;
+ dijit.setWaiState(this._colSelect.domNode,"label", dss(nls.waiColumnSelectTemplate, [idx]));
+ dijit.setWaiState(this._condSelect.domNode,"label", dss(nls.waiConditionSelectTemplate, [idx]));
+ dijit.setWaiState(this._pane._removeCBoxBtn.domNode,"label", dss(nls.waiRemoveRuleButtonTemplate, [idx]));
+ this._index = idx;
+ },
+ _getUsableConditions: function(type){
+ var conditions = 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(!dojo.isArray(typeDisabledConds)){
+ typeDisabledConds = [];
+ }
+ if(!dojo.isArray(colDisabledConds)){
+ colDisabledConds = [];
+ }
+ var arr = typeDisabledConds.concat(colDisabledConds);
+ if(arr.length){
+ var disabledConds = {};
+ dojo.forEach(arr, function(c){
+ if(dojo.isString(c)){
+ disabledConds[c.toLowerCase()] = true;
+ }
+ });
+ return dojo.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.
+ dijit.setWaiState(this._curValueBox.domNode, "label", dojo.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)){
+ dojo.mixin(res, {
+ store: g.store,
+ searchAttr: cell.field || cell.name,
+ fetchProperties: {
+ sort: [{"attribute": cell.field || cell.name}]
+ }
+ });
+ }
+ }else if(type == "boolean"){
+ dojo.mixin(res, this.dlg.builder.defaultArgs["boolean"]);
+ }
+ if(cell && cell.dataTypeArgs){
+ dojo.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 = dojo.date.locale.format;
+ if(cond == "range"){
+ return dojo.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";
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter.AccordionContainer", dijit.layout.AccordionContainer, {
+ nls: null,
+ addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
+ var pane = arguments[0] = child._pane = new dijit.layout.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){
+ dojo.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);
+ dojo.forEach(this.getChildren(), this._setupTitleDom);
+ },
+ startup: function(){
+ if(this._started){
+ return;
+ }
+ this.inherited(arguments);
+ if(parseInt(dojo.isIE, 10) == 7){
+ //IE7 will fire a lot of "onresize" event during initialization.
+ dojo.some(this._connects, function(cnnt){
+ if(cnnt[0][1] == "onresize"){
+ this.disconnect(cnnt);
+ return true;
+ }
+ }, this);
+ }
+ dojo.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 = dojo.keys, c = e.charOrCode, ltr = dojo._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();
+ }
+ dojo.stopEvent(e);
+ dojo.window.scrollIntoView(this.selectedChildWidget._buttonWidget.domNode.parentNode);
+ if(dojo.isIE){
+ //IE will not show focus indicator if tabIndex is -1
+ this.selectedChildWidget._removeCBoxBtn.focusNode.setAttribute("tabIndex", this._focusOnRemoveBtn ? _tabIdxes.accordionTitle : -1);
+ }
+ dijit.focus(this.selectedChildWidget[this._focusOnRemoveBtn ? "_removeCBoxBtn" : "_buttonWidget"].focusNode);
+ },
+ _modifyChild: function(child, isFirst){
+ if(!child || !this._started){
+ return;
+ }
+ dojo.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 dijit.form.Button({
+ label: this.nls.removeRuleButton,
+ showLabel: false,
+ iconClass: "dojoxGridFCBoxRemoveCBoxBtnIcon",
+ tabIndex: _tabIdxes.removeCBoxBtn,
+ onClick: dojo.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);
+ dojo.style(child._removeCBoxBtn.domNode, "display", "none");
+ }else{
+ for(i = 0; i < children.length; ++i){
+ if(children[i]._removeCBoxBtn){
+ dojo.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 = dojo.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 = dojo.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 = dojo.contentBox(child._buttonWidget.titleNode).w;
+ if(dojo.isIE < 8){ w -= 8; }
+ dojo.style(child._buttonWidget.titleTextNode, "width", w + "px");
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter.UniqueComboBox", dijit.form.ComboBox, {
+ _openResultList: function(results){
+ var cache = {}, s = this.store, colName = this.searchAttr;
+ arguments[0] = dojo.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 === dojo.keys.ENTER && this._opened){
+ dojo.stopEvent(evt);
+ }
+ this.inherited(arguments);
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter.BooleanValueBox", [dijit._Widget, dijit._Templated], {
+ templateString: dojo.cache("dojox.grid", "enhanced/templates/FilterBoolValueBox.html", "<div class=\"dojoxGridBoolValueBox\">\r\n\t<div class=\"dojoxGridTrueBox\">\r\n\t\t<input dojoType=\"dijit.form.RadioButton\" type='radio' name='a1' id='${_baseId}_rbTrue' checked=\"true\" \r\n\t\t\tdojoAttachPoint=\"rbTrue\" dojoAttachEvent=\"onChange: onChange\"/>\r\n\t\t<div class=\"dojoxGridTrueLabel\" for='${_baseId}_rbTrue'>${_lblTrue}</div>\r\n\t</div>\r\n\t<div class=\"dojoxGridFalseBox\">\r\n\t\t<input dojoType=\"dijit.form.RadioButton\" dojoAttachPoint=\"rbFalse\" type='radio' name='a1' id='${_baseId}_rbFalse'/>\r\n\t\t<div class=\"dojoxGridTrueLabel\" for='${_baseId}_rbFalse'>${_lblFalse}</div>\r\n\t</div>\r\n</div>\r\n"),
+ 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);
+ }
+ }
+});
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterLayer.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterLayer.js new file mode 100644 index 0000000..9125d4c --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterLayer.js @@ -0,0 +1,415 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterLayer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterLayer"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter.FilterLayer");
+
+dojo.require("dojox.grid.enhanced.plugins.filter._FilterExpr");
+dojo.require("dojox.grid.enhanced.plugins._StoreLayer");
+
+(function(){
+var ns = dojox.grid.enhanced.plugins,
+ cmdSetFilter = "filter",
+ cmdClearFilter = "clear",
+ hitchIfCan = function(scope, func){
+ return func ? dojo.hitch(scope || dojo.global, func) : function(){};
+ },
+ shallowClone = function(obj){
+ var res = {};
+ if(obj && dojo.isObject(obj)){
+ for(var name in obj){
+ res[name] = obj[name];
+ }
+ }
+ return res;
+ };
+ dojo.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.
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.ServerSideFilterLayer", [ns._ServerSideLayer, ns.filter._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 ? dojo.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);
+ };
+ }
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.ClientSideFilterLayer", [ns._StoreLayer, ns.filter._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 = dojo.isObject(args) ? args : {};
+ this.fetchAllOnFirstFilter(args.fetchAll);
+ this._getter = dojo.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(dojo.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(dojo.isArray(userRequest.sort) && userRequest.sort.length > 0 &&
+ //Sort info will stay here in every re-fetch, so remember it!
+ (sortStr = dojo.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 = dojo.hitch(this, this._onFetchBegin);
+ filterRequest.onComplete = dojo.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(!dojo.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 = dojo.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];
+ }
+ }
+ }
+ }
+ });
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterLayer.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterLayer.xd.js new file mode 100644 index 0000000..e4306ec --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterLayer.xd.js @@ -0,0 +1,421 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.filter.FilterLayer"],
+["require", "dojox.grid.enhanced.plugins.filter._FilterExpr"],
+["require", "dojox.grid.enhanced.plugins._StoreLayer"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterLayer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterLayer"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter.FilterLayer");
+
+dojo.require("dojox.grid.enhanced.plugins.filter._FilterExpr");
+dojo.require("dojox.grid.enhanced.plugins._StoreLayer");
+
+(function(){
+var ns = dojox.grid.enhanced.plugins,
+ cmdSetFilter = "filter",
+ cmdClearFilter = "clear",
+ hitchIfCan = function(scope, func){
+ return func ? dojo.hitch(scope || dojo.global, func) : function(){};
+ },
+ shallowClone = function(obj){
+ var res = {};
+ if(obj && dojo.isObject(obj)){
+ for(var name in obj){
+ res[name] = obj[name];
+ }
+ }
+ return res;
+ };
+ dojo.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.
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.ServerSideFilterLayer", [ns._ServerSideLayer, ns.filter._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 ? dojo.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);
+ };
+ }
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.ClientSideFilterLayer", [ns._StoreLayer, ns.filter._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 = dojo.isObject(args) ? args : {};
+ this.fetchAllOnFirstFilter(args.fetchAll);
+ this._getter = dojo.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(dojo.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(dojo.isArray(userRequest.sort) && userRequest.sort.length > 0 &&
+ //Sort info will stay here in every re-fetch, so remember it!
+ (sortStr = dojo.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 = dojo.hitch(this, this._onFetchBegin);
+ filterRequest.onComplete = dojo.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(!dojo.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 = dojo.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];
+ }
+ }
+ }
+ }
+ });
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterStatusTip.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterStatusTip.js new file mode 100644 index 0000000..c16ec58 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterStatusTip.js @@ -0,0 +1,150 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterStatusTip"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterStatusTip"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter.FilterStatusTip");
+
+dojo.requireLocalization("dojox.grid.enhanced", "Filter", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ru,sl,sv,th,tr,zh,zh-tw");
+dojo.require("dijit.TooltipDialog");
+dojo.require("dijit._base.popup");
+dojo.require("dijit.form.Button");
+dojo.require("dojo.string");
+dojo.require("dojo.date.locale");
+
+(function(){
+var gridCssCls = "", headerCssCls = "", cellCssCls = "", rowCssCls = "",
+ oddRowCssCls = "dojoxGridFStatusTipOddRow",
+ handleHolderCssCls = "dojoxGridFStatusTipHandle",
+ conditionCssCls = "dojoxGridFStatusTipCondition",
+ _removeRuleIconCls = "dojoxGridFStatusTipDelRuleBtnIcon",
+ _statusFooter = "</tbody></table>";
+
+ dojo.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 dojox.grid.enhanced.plugins.filter.FilterStatusPane();
+ this._dlg = new dijit.TooltipDialog({
+ "class": "dojoxGridFStatusTipDialog",
+ content: this.statusPane,
+ autofocus: false,
+ onMouseLeave: dojo.hitch(this,function(){
+ this.closeDialog();
+ })
+ });
+ this._dlg.connect(this._dlg.domNode,"click", dojo.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};
+ dijit.popup.close(this._dlg);
+ this._removedCriterias = [];
+ this._rules = [];
+ this._updateStatus(columnIdx);
+ dijit.popup.open({
+ popup: this._dlg,
+ parent: this.plugin.filterBar,
+ x:pos_x - 12,
+ y:pos_y - 3
+ });
+ },
+ closeDialog: function(){
+ dijit.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 = sp.statusRelPre.innerHTML = sp.statusRelPost.innerHTML = "";
+ var cell = p.grid.layout.cells[columnIdx];
+ var colName = cell ? "'" + (cell.name || cell.field) + "'" : nls["anycolumn"];
+ res = dojo.string.substitute(nls["statusTipMsg"], [colName]);
+ }else{
+ sp.statusTitle.innerHTML = nls["statusTipTitleHasFilter"];
+ sp.statusRelPre.innerHTML = nls["statusTipRelPre"] + " ";
+ sp.statusRelPost.innerHTML = " " + nls["statusTipRelPost"];
+ sp.statusRel.innerHTML = fdg._relOpCls == "logicall" ? nls["all"] : nls["any"];
+
+ 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 + dojo.map(this._rules, function(rule, i){
+ return this._getCriteriaStr(rule, i);
+ }, this).join('') + _statusFooter;
+ },
+ _addButtonForRules: function(){
+ if(this._rules.length > 1){
+ dojo.query("." + handleHolderCssCls, this.statusPane.statusDetailNode).forEach(dojo.hitch(this, function(nd, idx){
+ (new dijit.form.Button({
+ label: this.plugin.nls["removeRuleButton"],
+ showLabel: false,
+ iconClass: _removeRuleIconCls,
+ onClick: dojo.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, " </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));
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.FilterStatusPane", [dijit._Widget, dijit._Templated], {
+ templateString: dojo.cache("dojox.grid", "enhanced/templates/FilterStatusPane.html", "<div class=\"dojoxGridFStatusTip\">\r\n\t<div class=\"dojoxGridFStatusTipHead\">\r\n\t\t<span class=\"dojoxGridFStatusTipTitle\" dojoAttachPoint=\"statusTitle\"></span\r\n\t\t><span class=\"dojoxGridFStatusTipRelPre\" dojoAttachPoint=\"statusRelPre\"></span\r\n\t\t><span class=\"dojoxGridFStatusTipRel\" dojoAttachPoint=\"statusRel\"></span\r\n\t\t><span class=\"dojoxGridFStatusTipRelPost\" dojoAttachPoint=\"statusRelPost\"></span>\r\n\t</div>\r\n\t<div class=\"dojoxGridFStatusTipDetail\" dojoAttachPoint=\"statusDetailNode\"></div>\r\n</div>\r\n")
+ });
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterStatusTip.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterStatusTip.xd.js new file mode 100644 index 0000000..715e51c --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/FilterStatusTip.xd.js @@ -0,0 +1,160 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.filter.FilterStatusTip"],
+["requireLocalization", "dojox.grid.enhanced", "Filter", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ru,sl,sv,th,tr,zh,zh-tw", "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ru,sl,sv,th,tr,zh,zh-tw"],
+["require", "dijit.TooltipDialog"],
+["require", "dijit._base.popup"],
+["require", "dijit.form.Button"],
+["require", "dojo.string"],
+["require", "dojo.date.locale"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterStatusTip"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter.FilterStatusTip"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter.FilterStatusTip");
+
+;
+dojo.require("dijit.TooltipDialog");
+dojo.require("dijit._base.popup");
+dojo.require("dijit.form.Button");
+dojo.require("dojo.string");
+dojo.require("dojo.date.locale");
+
+(function(){
+var gridCssCls = "", headerCssCls = "", cellCssCls = "", rowCssCls = "",
+ oddRowCssCls = "dojoxGridFStatusTipOddRow",
+ handleHolderCssCls = "dojoxGridFStatusTipHandle",
+ conditionCssCls = "dojoxGridFStatusTipCondition",
+ _removeRuleIconCls = "dojoxGridFStatusTipDelRuleBtnIcon",
+ _statusFooter = "</tbody></table>";
+
+ dojo.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 dojox.grid.enhanced.plugins.filter.FilterStatusPane();
+ this._dlg = new dijit.TooltipDialog({
+ "class": "dojoxGridFStatusTipDialog",
+ content: this.statusPane,
+ autofocus: false,
+ onMouseLeave: dojo.hitch(this,function(){
+ this.closeDialog();
+ })
+ });
+ this._dlg.connect(this._dlg.domNode,"click", dojo.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};
+ dijit.popup.close(this._dlg);
+ this._removedCriterias = [];
+ this._rules = [];
+ this._updateStatus(columnIdx);
+ dijit.popup.open({
+ popup: this._dlg,
+ parent: this.plugin.filterBar,
+ x:pos_x - 12,
+ y:pos_y - 3
+ });
+ },
+ closeDialog: function(){
+ dijit.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 = sp.statusRelPre.innerHTML = sp.statusRelPost.innerHTML = "";
+ var cell = p.grid.layout.cells[columnIdx];
+ var colName = cell ? "'" + (cell.name || cell.field) + "'" : nls["anycolumn"];
+ res = dojo.string.substitute(nls["statusTipMsg"], [colName]);
+ }else{
+ sp.statusTitle.innerHTML = nls["statusTipTitleHasFilter"];
+ sp.statusRelPre.innerHTML = nls["statusTipRelPre"] + " ";
+ sp.statusRelPost.innerHTML = " " + nls["statusTipRelPost"];
+ sp.statusRel.innerHTML = fdg._relOpCls == "logicall" ? nls["all"] : nls["any"];
+
+ 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 + dojo.map(this._rules, function(rule, i){
+ return this._getCriteriaStr(rule, i);
+ }, this).join('') + _statusFooter;
+ },
+ _addButtonForRules: function(){
+ if(this._rules.length > 1){
+ dojo.query("." + handleHolderCssCls, this.statusPane.statusDetailNode).forEach(dojo.hitch(this, function(nd, idx){
+ (new dijit.form.Button({
+ label: this.plugin.nls["removeRuleButton"],
+ showLabel: false,
+ iconClass: _removeRuleIconCls,
+ onClick: dojo.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, " </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));
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.FilterStatusPane", [dijit._Widget, dijit._Templated], {
+ templateString: dojo.cache("dojox.grid", "enhanced/templates/FilterStatusPane.html", "<div class=\"dojoxGridFStatusTip\">\r\n\t<div class=\"dojoxGridFStatusTipHead\">\r\n\t\t<span class=\"dojoxGridFStatusTipTitle\" dojoAttachPoint=\"statusTitle\"></span\r\n\t\t><span class=\"dojoxGridFStatusTipRelPre\" dojoAttachPoint=\"statusRelPre\"></span\r\n\t\t><span class=\"dojoxGridFStatusTipRel\" dojoAttachPoint=\"statusRel\"></span\r\n\t\t><span class=\"dojoxGridFStatusTipRelPost\" dojoAttachPoint=\"statusRelPost\"></span>\r\n\t</div>\r\n\t<div class=\"dojoxGridFStatusTipDetail\" dojoAttachPoint=\"statusDetailNode\"></div>\r\n</div>\r\n")
+ });
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_ConditionExpr.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_ConditionExpr.js new file mode 100644 index 0000000..cf1c4e3 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_ConditionExpr.js @@ -0,0 +1,226 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter._ConditionExpr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter._ConditionExpr"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter._ConditionExpr");
+
+(function(){
+ var fns = dojox.grid.enhanced.plugins.filter;
+
+dojo.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
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter._DataExpr", fns._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(dojo.isFunction(this._convertArgs.convert)){
+ this._convertData = dojo.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 (dojo.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
+ };
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter._OperatorExpr", fns._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(dojo.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: dojo.map(this._operands,function(operand){
+ return operand.toObject();
+ })
+ };
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter._UniOpExpr", fns._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 fns._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");
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter._BiOpExpr", fns._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 fns._ConditionExpr)){
+ throw new Error("_BiOpExpr: left operand is not expression.");
+ }else if(!(this._operands[1] instanceof fns._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");
+ }
+});
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_ConditionExpr.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_ConditionExpr.xd.js new file mode 100644 index 0000000..552d8b8 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_ConditionExpr.xd.js @@ -0,0 +1,230 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.filter._ConditionExpr"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter._ConditionExpr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter._ConditionExpr"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter._ConditionExpr");
+
+(function(){
+ var fns = dojox.grid.enhanced.plugins.filter;
+
+dojo.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
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter._DataExpr", fns._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(dojo.isFunction(this._convertArgs.convert)){
+ this._convertData = dojo.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 (dojo.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
+ };
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter._OperatorExpr", fns._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(dojo.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: dojo.map(this._operands,function(operand){
+ return operand.toObject();
+ })
+ };
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter._UniOpExpr", fns._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 fns._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");
+ }
+});
+dojo.declare("dojox.grid.enhanced.plugins.filter._BiOpExpr", fns._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 fns._ConditionExpr)){
+ throw new Error("_BiOpExpr: left operand is not expression.");
+ }else if(!(this._operands[1] instanceof fns._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");
+ }
+});
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_DataExprs.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_DataExprs.js new file mode 100644 index 0000000..dc1ff36 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_DataExprs.js @@ -0,0 +1,89 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter._DataExprs"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter._DataExprs"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter._DataExprs");
+
+dojo.require("dojox.grid.enhanced.plugins.filter._ConditionExpr");
+dojo.require("dojo.date.locale");
+
+(function(){
+ var fns = dojox.grid.enhanced.plugins.filter;
+
+ dojo.declare("dojox.grid.enhanced.plugins.filter.BooleanExpr", fns._DataExpr, {
+ // summary:
+ // A condition expression wrapper for boolean values
+ _name: "bool",
+ _convertData: function(/* anything */dataValue){
+ // summary:
+ // override from _DataExpr
+ return !!dataValue; //Boolean
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.StringExpr", fns._DataExpr, {
+ // summary:
+ // A condition expression wrapper for string values
+ _name: "string",
+ _convertData: function(/* anything */dataValue){
+ // summary:
+ // override from _DataExpr
+ return String(dataValue); //String
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.NumberExpr", fns._DataExpr, {
+ // summary:
+ // A condition expression wrapper for number values
+ _name: "number",
+ _convertDataToExpr: function(/* anything */dataValue){
+ // summary:
+ // override from _DataExpr
+ return parseFloat(dataValue); //Number
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.DateExpr", fns._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 = dojo.date.locale.parse(String(dataValue), dojo.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);
+ }
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.TimeExpr", fns.DateExpr, {
+ // summary:
+ // A condition expression wrapper for time values
+ _name: "time"
+ });
+})();
+
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_DataExprs.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_DataExprs.xd.js new file mode 100644 index 0000000..227cc90 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_DataExprs.xd.js @@ -0,0 +1,95 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.filter._DataExprs"],
+["require", "dojox.grid.enhanced.plugins.filter._ConditionExpr"],
+["require", "dojo.date.locale"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter._DataExprs"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter._DataExprs"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter._DataExprs");
+
+dojo.require("dojox.grid.enhanced.plugins.filter._ConditionExpr");
+dojo.require("dojo.date.locale");
+
+(function(){
+ var fns = dojox.grid.enhanced.plugins.filter;
+
+ dojo.declare("dojox.grid.enhanced.plugins.filter.BooleanExpr", fns._DataExpr, {
+ // summary:
+ // A condition expression wrapper for boolean values
+ _name: "bool",
+ _convertData: function(/* anything */dataValue){
+ // summary:
+ // override from _DataExpr
+ return !!dataValue; //Boolean
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.StringExpr", fns._DataExpr, {
+ // summary:
+ // A condition expression wrapper for string values
+ _name: "string",
+ _convertData: function(/* anything */dataValue){
+ // summary:
+ // override from _DataExpr
+ return String(dataValue); //String
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.NumberExpr", fns._DataExpr, {
+ // summary:
+ // A condition expression wrapper for number values
+ _name: "number",
+ _convertDataToExpr: function(/* anything */dataValue){
+ // summary:
+ // override from _DataExpr
+ return parseFloat(dataValue); //Number
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.DateExpr", fns._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 = dojo.date.locale.parse(String(dataValue), dojo.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);
+ }
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.TimeExpr", fns.DateExpr, {
+ // summary:
+ // A condition expression wrapper for time values
+ _name: "time"
+ });
+})();
+
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_FilterExpr.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_FilterExpr.js new file mode 100644 index 0000000..397913c --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_FilterExpr.js @@ -0,0 +1,239 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter._FilterExpr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter._FilterExpr"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter._FilterExpr");
+//This is the main file that should be 'required' if filter expression facility is necessary.
+
+dojo.require("dojox.grid.enhanced.plugins.filter._DataExprs");
+dojo.require("dojo.date");
+
+(function(){
+ var fns = dojox.grid.enhanced.plugins.filter;
+ /* Logic Operations */
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LogicAND", fns._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 fns.BooleanExpr(res); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LogicOR", fns._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 fns.BooleanExpr(res); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LogicXOR", fns._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 fns.BooleanExpr((!!left_res) != (!!right_res)); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LogicNOT", fns._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 fns.BooleanExpr(!operand.applyRow(datarow, getter).getValue()); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LogicALL", fns._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 fns._ConditionExpr); ++i){
+ res = this._operands[i].applyRow(datarow,getter).getValue();
+ }
+ return new fns.BooleanExpr(res); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LogicANY", fns._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 fns._ConditionExpr); ++i){
+ res = this._operands[i].applyRow(datarow,getter).getValue();
+ }
+ return new fns.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 fns.TimeExpr){
+ return dojo.date.compare(left_res,right_res,"time");
+ }else if(left instanceof fns.DateExpr){
+ return dojo.date.compare(left_res,right_res,"date");
+ }else{
+ if(left instanceof fns.StringExpr){
+ left_res = left_res.toLowerCase();
+ right_res = String(right_res).toLowerCase();
+ }
+ return left_res == right_res ? 0 : (left_res < right_res ? -1 : 1);
+ }
+ }
+ dojo.declare("dojox.grid.enhanced.plugins.filter.EqualTo", fns._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 fns.BooleanExpr(res === 0); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LessThan", fns._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 fns.BooleanExpr(res < 0); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LessThanOrEqualTo", fns._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 fns.BooleanExpr(res <= 0); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LargerThan", fns._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 fns.BooleanExpr(res > 0); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LargerThanOrEqualTo", fns._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 fns.BooleanExpr(res >= 0); //_ConditionExpr
+ }
+ });
+
+ /* String Operations */
+ dojo.declare("dojox.grid.enhanced.plugins.filter.Contains", fns._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 fns.BooleanExpr(left_res.indexOf(right_res) >= 0); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.StartsWith", fns._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 fns.BooleanExpr(left_res.substring(0, right_res.length) == right_res); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.EndsWith", fns._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 fns.BooleanExpr(left_res.substring(left_res.length - right_res.length) == right_res); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.Matches", fns._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 fns.BooleanExpr(left_res.search(right_res) >= 0); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.IsEmpty", fns._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 fns.BooleanExpr(res === "" || res == null);
+ }
+ });
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_FilterExpr.xd.js b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_FilterExpr.xd.js new file mode 100644 index 0000000..5e8b738 --- /dev/null +++ b/js/dojo-1.6/dojox/grid/enhanced/plugins/filter/_FilterExpr.xd.js @@ -0,0 +1,245 @@ +/*
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.grid.enhanced.plugins.filter._FilterExpr"],
+["require", "dojox.grid.enhanced.plugins.filter._DataExprs"],
+["require", "dojo.date"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.grid.enhanced.plugins.filter._FilterExpr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.enhanced.plugins.filter._FilterExpr"] = true;
+dojo.provide("dojox.grid.enhanced.plugins.filter._FilterExpr");
+//This is the main file that should be 'required' if filter expression facility is necessary.
+
+dojo.require("dojox.grid.enhanced.plugins.filter._DataExprs");
+dojo.require("dojo.date");
+
+(function(){
+ var fns = dojox.grid.enhanced.plugins.filter;
+ /* Logic Operations */
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LogicAND", fns._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 fns.BooleanExpr(res); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LogicOR", fns._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 fns.BooleanExpr(res); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LogicXOR", fns._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 fns.BooleanExpr((!!left_res) != (!!right_res)); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LogicNOT", fns._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 fns.BooleanExpr(!operand.applyRow(datarow, getter).getValue()); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LogicALL", fns._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 fns._ConditionExpr); ++i){
+ res = this._operands[i].applyRow(datarow,getter).getValue();
+ }
+ return new fns.BooleanExpr(res); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LogicANY", fns._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 fns._ConditionExpr); ++i){
+ res = this._operands[i].applyRow(datarow,getter).getValue();
+ }
+ return new fns.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 fns.TimeExpr){
+ return dojo.date.compare(left_res,right_res,"time");
+ }else if(left instanceof fns.DateExpr){
+ return dojo.date.compare(left_res,right_res,"date");
+ }else{
+ if(left instanceof fns.StringExpr){
+ left_res = left_res.toLowerCase();
+ right_res = String(right_res).toLowerCase();
+ }
+ return left_res == right_res ? 0 : (left_res < right_res ? -1 : 1);
+ }
+ }
+ dojo.declare("dojox.grid.enhanced.plugins.filter.EqualTo", fns._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 fns.BooleanExpr(res === 0); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LessThan", fns._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 fns.BooleanExpr(res < 0); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LessThanOrEqualTo", fns._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 fns.BooleanExpr(res <= 0); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LargerThan", fns._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 fns.BooleanExpr(res > 0); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.LargerThanOrEqualTo", fns._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 fns.BooleanExpr(res >= 0); //_ConditionExpr
+ }
+ });
+
+ /* String Operations */
+ dojo.declare("dojox.grid.enhanced.plugins.filter.Contains", fns._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 fns.BooleanExpr(left_res.indexOf(right_res) >= 0); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.StartsWith", fns._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 fns.BooleanExpr(left_res.substring(0, right_res.length) == right_res); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.EndsWith", fns._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 fns.BooleanExpr(left_res.substring(left_res.length - right_res.length) == right_res); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.Matches", fns._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 fns.BooleanExpr(left_res.search(right_res) >= 0); //_ConditionExpr
+ }
+ });
+ dojo.declare("dojox.grid.enhanced.plugins.filter.IsEmpty", fns._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 fns.BooleanExpr(res === "" || res == null);
+ }
+ });
+})();
+
+}
+
+}};});
|
