summaryrefslogtreecommitdiff
path: root/includes/js/dojox/grid
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dojox/grid')
-rw-r--r--includes/js/dojox/grid/Grid.js363
-rw-r--r--includes/js/dojox/grid/README39
-rw-r--r--includes/js/dojox/grid/VirtualGrid.js779
-rw-r--r--includes/js/dojox/grid/_data/dijitEditors.js170
-rw-r--r--includes/js/dojox/grid/_data/editors.js239
-rw-r--r--includes/js/dojox/grid/_data/fields.js104
-rw-r--r--includes/js/dojox/grid/_data/model.js762
-rw-r--r--includes/js/dojox/grid/_grid/Grid.css201
-rw-r--r--includes/js/dojox/grid/_grid/Grid.css.commented.css258
-rw-r--r--includes/js/dojox/grid/_grid/Grid_rtl.css8
-rw-r--r--includes/js/dojox/grid/_grid/Grid_rtl.css.commented.css10
-rw-r--r--includes/js/dojox/grid/_grid/builder.js522
-rw-r--r--includes/js/dojox/grid/_grid/cell.js66
-rw-r--r--includes/js/dojox/grid/_grid/drag.js113
-rw-r--r--includes/js/dojox/grid/_grid/edit.js238
-rw-r--r--includes/js/dojox/grid/_grid/focus.js207
-rw-r--r--includes/js/dojox/grid/_grid/images/grid_dx_gradient.gifbin0 -> 267 bytes
-rw-r--r--includes/js/dojox/grid/_grid/images/grid_sort_down.gifbin0 -> 49 bytes
-rw-r--r--includes/js/dojox/grid/_grid/images/grid_sort_up.gifbin0 -> 48 bytes
-rw-r--r--includes/js/dojox/grid/_grid/images/tabEnabled_rotated.pngbin0 -> 94 bytes
-rw-r--r--includes/js/dojox/grid/_grid/images/tabHover_rotated.pngbin0 -> 106 bytes
-rw-r--r--includes/js/dojox/grid/_grid/layout.js75
-rw-r--r--includes/js/dojox/grid/_grid/lib.js254
-rw-r--r--includes/js/dojox/grid/_grid/nihiloGrid.css211
-rw-r--r--includes/js/dojox/grid/_grid/nihiloGrid.css.commented.css275
-rw-r--r--includes/js/dojox/grid/_grid/publicEvents.js451
-rw-r--r--includes/js/dojox/grid/_grid/rowbar.js53
-rw-r--r--includes/js/dojox/grid/_grid/rows.js66
-rw-r--r--includes/js/dojox/grid/_grid/scroller.js489
-rw-r--r--includes/js/dojox/grid/_grid/selection.js215
-rw-r--r--includes/js/dojox/grid/_grid/soriaGrid.css212
-rw-r--r--includes/js/dojox/grid/_grid/soriaGrid.css.commented.css276
-rw-r--r--includes/js/dojox/grid/_grid/tundraGrid.css215
-rw-r--r--includes/js/dojox/grid/_grid/tundraGrid.css.commented.css281
-rw-r--r--includes/js/dojox/grid/_grid/view.js336
-rw-r--r--includes/js/dojox/grid/_grid/views.js277
-rw-r--r--includes/js/dojox/grid/resources/GridView.html12
-rw-r--r--includes/js/dojox/grid/resources/VirtualGrid.html5
-rw-r--r--includes/js/dojox/grid/tests/databaseModel.js337
-rw-r--r--includes/js/dojox/grid/tests/images/closed.gifbin0 -> 907 bytes
-rw-r--r--includes/js/dojox/grid/tests/images/flatScreen.gifbin0 -> 824 bytes
-rw-r--r--includes/js/dojox/grid/tests/images/open.gifbin0 -> 907 bytes
-rw-r--r--includes/js/dojox/grid/tests/support/books.xml103
-rw-r--r--includes/js/dojox/grid/tests/support/data.php379
-rw-r--r--includes/js/dojox/grid/tests/support/geography.xml51
-rw-r--r--includes/js/dojox/grid/tests/support/json.php794
-rw-r--r--includes/js/dojox/grid/tests/support/movies.csv9
-rw-r--r--includes/js/dojox/grid/tests/support/test_data.js30
-rw-r--r--includes/js/dojox/grid/tests/support/test_data_objects.js31
-rw-r--r--includes/js/dojox/grid/tests/support/testtbl.sql944
-rw-r--r--includes/js/dojox/grid/tests/support/yahoo_search.js131
-rw-r--r--includes/js/dojox/grid/tests/test_change_structure.html124
-rw-r--r--includes/js/dojox/grid/tests/test_custom_sort.html86
-rw-r--r--includes/js/dojox/grid/tests/test_dojo_data_edit.html124
-rw-r--r--includes/js/dojox/grid/tests/test_dojo_data_empty.html63
-rw-r--r--includes/js/dojox/grid/tests/test_dojo_data_model.html84
-rw-r--r--includes/js/dojox/grid/tests/test_dojo_data_model_EmptyResultSet.html57
-rw-r--r--includes/js/dojox/grid/tests/test_dojo_data_model_multiStores.html291
-rw-r--r--includes/js/dojox/grid/tests/test_dojo_data_model_processError.html65
-rw-r--r--includes/js/dojox/grid/tests/test_dojo_data_notification.html114
-rw-r--r--includes/js/dojox/grid/tests/test_edit.html149
-rw-r--r--includes/js/dojox/grid/tests/test_edit_canEdit.html156
-rw-r--r--includes/js/dojox/grid/tests/test_edit_dijit.html137
-rw-r--r--includes/js/dojox/grid/tests/test_events.html174
-rw-r--r--includes/js/dojox/grid/tests/test_expand.html107
-rw-r--r--includes/js/dojox/grid/tests/test_grid.html69
-rw-r--r--includes/js/dojox/grid/tests/test_grid_dlg.html88
-rw-r--r--includes/js/dojox/grid/tests/test_grid_headerHeight.html84
-rw-r--r--includes/js/dojox/grid/tests/test_grid_layout.html112
-rw-r--r--includes/js/dojox/grid/tests/test_grid_layout_LayoutContainer.html87
-rw-r--r--includes/js/dojox/grid/tests/test_grid_layout_borderContainer.html98
-rw-r--r--includes/js/dojox/grid/tests/test_grid_object_model_change.html86
-rw-r--r--includes/js/dojox/grid/tests/test_grid_programmatic.html65
-rw-r--r--includes/js/dojox/grid/tests/test_grid_programmatic_layout.html74
-rw-r--r--includes/js/dojox/grid/tests/test_grid_rtl.html71
-rw-r--r--includes/js/dojox/grid/tests/test_grid_themes.html118
-rw-r--r--includes/js/dojox/grid/tests/test_grid_tooltip_menu.html161
-rw-r--r--includes/js/dojox/grid/tests/test_keyboard.html90
-rw-r--r--includes/js/dojox/grid/tests/test_markup.html112
-rw-r--r--includes/js/dojox/grid/tests/test_mysql_edit.html155
-rw-r--r--includes/js/dojox/grid/tests/test_sizing.html175
-rw-r--r--includes/js/dojox/grid/tests/test_sizing_100rows.html168
-rw-r--r--includes/js/dojox/grid/tests/test_sizing_ResizeHandle.html113
-rw-r--r--includes/js/dojox/grid/tests/test_styling.html131
-rw-r--r--includes/js/dojox/grid/tests/test_subgrid.html179
-rw-r--r--includes/js/dojox/grid/tests/test_tundra_edit.html139
-rw-r--r--includes/js/dojox/grid/tests/test_yahoo_images.html148
-rw-r--r--includes/js/dojox/grid/tests/test_yahoo_search.html141
-rw-r--r--includes/js/dojox/grid/tests/yahooSearch.js137
89 files changed, 15123 insertions, 0 deletions
diff --git a/includes/js/dojox/grid/Grid.js b/includes/js/dojox/grid/Grid.js
new file mode 100644
index 0000000..309bb25
--- /dev/null
+++ b/includes/js/dojox/grid/Grid.js
@@ -0,0 +1,363 @@
+if(!dojo._hasResource["dojox.grid.Grid"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.Grid"] = true;
+dojo.provide("dojox.grid.Grid");
+dojo.require("dojox.grid.VirtualGrid");
+dojo.require("dojox.grid._data.model");
+dojo.require("dojox.grid._data.editors");
+dojo.require("dojox.grid._data.dijitEditors");
+
+// FIXME:
+// we are at the wrong location!
+
+dojo.declare('dojox.Grid', dojox.VirtualGrid, {
+ // summary:
+ // A grid widget with virtual scrolling, cell editing, complex rows,
+ // sorting, fixed columns, sizeable columns, etc.
+ // description:
+ // Grid is a subclass of VirtualGrid, providing binding to a data
+ // store.
+ // example:
+ // define the grid structure:
+ // | var structure = [ // array of view objects
+ // | { cells: [// array of rows, a row is an array of cells
+ // | [ { name: "Alpha", width: 6 },
+ // | { name: "Beta" },
+ // | { name: "Gamma", get: formatFunction }
+ // | ]
+ // | ]}
+ // | ];
+ //
+ // define a grid data model
+ // | var model = new dojox.grid.data.table(null, data);
+ // |
+ // | <div id="grid" model="model" structure="structure"
+ // | dojoType="dojox.VirtualGrid"></div>
+ //
+
+ // model:
+ // string or object grid data model
+ model: 'dojox.grid.data.Table',
+
+ // life cycle
+ postCreate: function(){
+ if(this.model){
+ var m = this.model;
+ if(dojo.isString(m)){
+ m = dojo.getObject(m);
+ }
+ this.model = (dojo.isFunction(m)) ? new m() : m;
+ this._setModel(this.model);
+ }
+ this.inherited(arguments);
+ },
+
+ destroy: function(){
+ this.setModel(null);
+ this.inherited(arguments);
+ },
+
+ // structure
+ _structureChanged: function() {
+ this.indexCellFields();
+ this.inherited(arguments);
+ },
+
+ // model
+ _setModel: function(inModel){
+ // if(!inModel){ return; }
+ this.model = inModel;
+ if(this.model){
+ this.model.observer(this);
+ this.model.measure();
+ this.indexCellFields();
+ }
+ },
+
+ setModel: function(inModel){
+ // summary:
+ // Set the grid's data model
+ // inModel: Object
+ // Model object, usually an instance of a dojox.grid.data.Model
+ // subclass
+ if(this.model){
+ this.model.notObserver(this);
+ }
+ this._setModel(inModel);
+ },
+
+
+ get: function(inRowIndex){
+ // summary: data socket (called in cell's context)
+ return this.grid.model.getDatum(inRowIndex, this.fieldIndex);
+ },
+
+ // model modifications
+ modelAllChange: function(){
+ this.rowCount = (this.model ? this.model.getRowCount() : 0);
+ this.updateRowCount(this.rowCount);
+ },
+
+ modelRowChange: function(inData, inRowIndex){
+ this.updateRow(inRowIndex);
+ },
+
+ modelDatumChange: function(inDatum, inRowIndex, inFieldIndex){
+ this.updateRow(inRowIndex);
+ },
+
+ modelFieldsChange: function() {
+ this.indexCellFields();
+ this.render();
+ },
+
+ // model insertion
+ modelInsertion: function(inRowIndex){
+ this.updateRowCount(this.model.getRowCount());
+ },
+
+ // model removal
+ modelRemoval: function(inKeys){
+ this.updateRowCount(this.model.getRowCount());
+ },
+
+ // cells
+ getCellName: function(inCell){
+ var v = this.model.fields.values, i = inCell.fieldIndex;
+ return i>=0 && i<v.length && v[i].name || this.inherited(arguments);
+ },
+
+ indexCellFields: function(){
+ var cells = this.layout.cells;
+ for(var i=0, c; cells && (c=cells[i]); i++){
+ if(dojo.isString(c.field)){
+ c.fieldIndex = this.model.fields.indexOf(c.field);
+ }
+ }
+ },
+
+ // utility
+ refresh: function(){
+ // summary:
+ // Re-render the grid, getting new data from the model
+ this.edit.cancel();
+ this.model.measure();
+ },
+
+ // sorting
+ canSort: function(inSortInfo){
+ var f = this.getSortField(inSortInfo);
+ // 0 is not a valid sort field
+ return f && this.model.canSort(f);
+ },
+
+ getSortField: function(inSortInfo){
+ // summary:
+ // Retrieves the model field on which to sort data.
+ // inSortInfo: Integer
+ // 1-based grid column index; positive if sort is ascending, otherwise negative
+ var c = this.getCell(this.getSortIndex(inSortInfo));
+ // we expect c.fieldIndex == -1 for non model fields
+ // that yields a getSortField value of 0, which can be detected as invalid
+ return (c.fieldIndex+1) * (this.sortInfo > 0 ? 1 : -1);
+ },
+
+ sort: function(){
+ this.edit.apply();
+ this.model.sort(this.getSortField());
+ },
+
+ // row editing
+ addRow: function(inRowData, inIndex){
+ this.edit.apply();
+ var i = inIndex || -1;
+ if(i<0){
+ i = this.selection.getFirstSelected() || 0;
+ }
+ if(i<0){
+ i = 0;
+ }
+ this.model.insert(inRowData, i);
+ this.model.beginModifyRow(i);
+ // begin editing row
+ // FIXME: add to edit
+ for(var j=0, c; ((c=this.getCell(j)) && !c.editor); j++){}
+ if(c&&c.editor){
+ this.edit.setEditCell(c, i);
+ this.focus.setFocusCell(c, i);
+ }else{
+ this.focus.setFocusCell(this.getCell(0), i);
+ }
+ },
+
+ removeSelectedRows: function(){
+ this.edit.apply();
+ var s = this.selection.getSelected();
+ if(s.length){
+ this.model.remove(s);
+ this.selection.clear();
+ }
+ },
+
+ //: protected
+ // editing
+ canEdit: function(inCell, inRowIndex){
+ // summary:
+ // Determines if a given cell may be edited
+ // inCell: Object
+ // A grid cell
+ // inRowIndex: Integer
+ // Grid row index
+ // returns: Boolean
+ // True if given cell may be edited
+ return (this.model.canModify ? this.model.canModify(inRowIndex) : true);
+ },
+
+ doStartEdit: function(inCell, inRowIndex){
+ this.model.beginModifyRow(inRowIndex);
+ this.onStartEdit(inCell, inRowIndex);
+ },
+
+ doApplyCellEdit: function(inValue, inRowIndex, inFieldIndex){
+ this.model.setDatum(inValue, inRowIndex, inFieldIndex);
+ this.onApplyCellEdit(inValue, inRowIndex, inFieldIndex);
+ },
+
+ doCancelEdit: function(inRowIndex){
+ this.model.cancelModifyRow(inRowIndex);
+ this.onCancelEdit.apply(this, arguments);
+ },
+
+ doApplyEdit: function(inRowIndex){
+ this.model.endModifyRow(inRowIndex);
+ this.onApplyEdit(inRowIndex);
+ },
+
+ styleRowState: function(inRow){
+ // summary: Perform row styling
+ if(this.model.getState){
+ var states=this.model.getState(inRow.index), c='';
+ for(var i=0, ss=["inflight", "error", "inserting"], s; s=ss[i]; i++){
+ if(states[s]){
+ c = ' dojoxGrid-row-' + s;
+ break;
+ }
+ }
+ inRow.customClasses += c;
+ }
+ },
+
+ onStyleRow: function(inRow){
+ this.styleRowState(inRow);
+ this.inherited(arguments);
+ }
+
+});
+
+dojox.Grid.markupFactory = function(props, node, ctor){
+ // handle setting up a data model for a store if one
+ // isn't provided. There are some caveats:
+ // * we only really handle dojo.data sources well. They're the future
+ // so it's no big deal, but it's something to be aware of.
+ // * I'm pretty sure that colgroup introspection is missing some of
+ // the available settable properties.
+ // * No handling of cell formatting and content getting is done
+ var d = dojo;
+ var widthFromAttr = function(n){
+ var w = d.attr(n, "width")||"auto";
+ if((w != "auto")&&(w.substr(-2) != "em")){
+ w = parseInt(w)+"px";
+ }
+ return w;
+ }
+ if(!props.model && d.hasAttr(node, "store")){
+ // if a model isn't specified and we point to a store, assume
+ // we're also folding the definition for a model up into the
+ // inline ctor for the Grid. This will then take properties
+ // like "query", "rowsPerPage", and "clientSort" from the grid
+ // definition.
+ var mNode = node.cloneNode(false);
+ d.attr(mNode, {
+ "jsId": null,
+ "dojoType": d.attr(node, "dataModelClass") || "dojox.grid.data.DojoData"
+ });
+ props.model = d.parser.instantiate([mNode])[0];
+ }
+ // if(!props.model){ console.debug("no model!"); }
+ // if a structure isn't referenced, do we have enough
+ // data to try to build one automatically?
+ if( !props.structure &&
+ node.nodeName.toLowerCase() == "table"){
+
+ // try to discover a structure
+ props.structure = d.query("> colgroup", node).map(function(cg){
+ var sv = d.attr(cg, "span");
+ var v = {
+ noscroll: (d.attr(cg, "noscroll") == "true") ? true : false,
+ __span: (!!sv ? parseInt(sv) : 1),
+ cells: []
+ };
+ if(d.hasAttr(cg, "width")){
+ v.width = widthFromAttr(cg);
+ }
+ return v; // for vendetta
+ });
+ if(!props.structure.length){
+ props.structure.push({
+ __span: Infinity,
+ cells: [] // catch-all view
+ });
+ }
+ // check to see if we're gonna have more than one view
+
+ // for each tr in our th, create a row of cells
+ d.query("thead > tr", node).forEach(function(tr, tr_idx){
+ var cellCount = 0;
+ var viewIdx = 0;
+ var lastViewIdx;
+ var cView = null;
+ d.query("> th", tr).map(function(th){
+ // what view will this cell go into?
+
+ // NOTE:
+ // to prevent extraneous iteration, we start counters over
+ // for each row, incrementing over the surface area of the
+ // structure that colgroup processing generates and
+ // creating cell objects for each <th> to place into those
+ // cell groups. There's a lot of state-keepking logic
+ // here, but it is what it has to be.
+ if(!cView){ // current view book keeping
+ lastViewIdx = 0;
+ cView = props.structure[0];
+ }else if(cellCount >= (lastViewIdx+cView.__span)){
+ viewIdx++;
+ // move to allocating things into the next view
+ lastViewIdx += cView.__span;
+ lastView = cView;
+ cView = props.structure[viewIdx];
+ }
+
+ // actually define the cell from what markup hands us
+ var cell = {
+ name: d.trim(d.attr(th, "name")||th.innerHTML),
+ field: d.trim(d.attr(th, "field")||""),
+ colSpan: parseInt(d.attr(th, "colspan")||1)
+ };
+ cellCount += cell.colSpan;
+ cell.field = cell.field||cell.name;
+ cell.width = widthFromAttr(th);
+ if(!cView.cells[tr_idx]){
+ cView.cells[tr_idx] = [];
+ }
+ cView.cells[tr_idx].push(cell);
+ });
+ });
+ // console.debug(dojo.toJson(props.structure, true));
+ }
+ return new dojox.Grid(props, node);
+}
+
+
+// alias us to the right location
+dojox.grid.Grid = dojox.Grid;
+
+}
diff --git a/includes/js/dojox/grid/README b/includes/js/dojox/grid/README
new file mode 100644
index 0000000..f9dade3
--- /dev/null
+++ b/includes/js/dojox/grid/README
@@ -0,0 +1,39 @@
+-------------------------------------------------------------------------------
+dojox.grid
+-------------------------------------------------------------------------------
+Version 1.00
+Release date: 10/04/2007
+-------------------------------------------------------------------------------
+Project state:
+beta
+-------------------------------------------------------------------------------
+Credits
+ Scott J. Miles (sjmiles@activegrid.com)
+ Steve Orvell (sorvell@activegrid.com)
+-------------------------------------------------------------------------------
+Project description
+
+TurboGrid has been made available in Dojo and is now the dojox.grid!
+
+-------------------------------------------------------------------------------
+Dependencies:
+
+Dojo Core
+Dijit Templated Widget
+-------------------------------------------------------------------------------
+Documentation
+
+None available for this version yet.
+
+See http://www.turboajax.com/products/turbogrid/ for legacy documentation.
+-------------------------------------------------------------------------------
+Installation instructions
+
+Grab the following from the Dojo SVN Repository:
+http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/grid/*
+
+Install into the following directory structure:
+/dojox/grid/
+
+...which should be at the same level as your Dojo checkout.
+-------------------------------------------------------------------------------
diff --git a/includes/js/dojox/grid/VirtualGrid.js b/includes/js/dojox/grid/VirtualGrid.js
new file mode 100644
index 0000000..104054c
--- /dev/null
+++ b/includes/js/dojox/grid/VirtualGrid.js
@@ -0,0 +1,779 @@
+if(!dojo._hasResource["dojox.grid.VirtualGrid"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.VirtualGrid"] = true;
+dojo.provide("dojox.grid.VirtualGrid");
+
+dojo.require("dojox.grid._grid.lib");
+dojo.require("dojox.grid._grid.scroller");
+dojo.require("dojox.grid._grid.view");
+dojo.require("dojox.grid._grid.views");
+dojo.require("dojox.grid._grid.layout");
+dojo.require("dojox.grid._grid.rows");
+dojo.require("dojox.grid._grid.focus");
+dojo.require("dojox.grid._grid.selection");
+dojo.require("dojox.grid._grid.edit");
+dojo.require("dojox.grid._grid.rowbar");
+dojo.require("dojox.grid._grid.publicEvents");
+
+dojo.declare('dojox.VirtualGrid',
+ [ dijit._Widget, dijit._Templated ],
+ {
+ // summary:
+ // A grid widget with virtual scrolling, cell editing, complex rows,
+ // sorting, fixed columns, sizeable columns, etc.
+ //
+ // description:
+ // VirtualGrid provides the full set of grid features without any
+ // direct connection to a data store.
+ //
+ // The grid exposes a get function for the grid, or optionally
+ // individual columns, to populate cell contents.
+ //
+ // The grid is rendered based on its structure, an object describing
+ // column and cell layout.
+ //
+ // example:
+ // A quick sample:
+ //
+ // define a get function
+ // | function get(inRowIndex){ // called in cell context
+ // | return [this.index, inRowIndex].join(', ');
+ // | }
+ //
+ // define the grid structure:
+ // | var structure = [ // array of view objects
+ // | { cells: [// array of rows, a row is an array of cells
+ // | [
+ // | { name: "Alpha", width: 6 },
+ // | { name: "Beta" },
+ // | { name: "Gamma", get: get }]
+ // | ]}
+ // | ];
+ //
+ // | <div id="grid"
+ // | rowCount="100" get="get"
+ // | structure="structure"
+ // | dojoType="dojox.VirtualGrid"></div>
+
+ templateString:"<div class=\"dojoxGrid\" hidefocus=\"hidefocus\" role=\"wairole:grid\">\n\t<div class=\"dojoxGrid-master-header\" dojoAttachPoint=\"viewsHeaderNode\"></div>\n\t<div class=\"dojoxGrid-master-view\" dojoAttachPoint=\"viewsNode\"></div>\n\t<span dojoAttachPoint=\"lastFocusNode\" tabindex=\"0\"></span>\n</div>\n",
+
+ // classTag: String
+ // CSS class applied to the grid's domNode
+ classTag: 'dojoxGrid',
+
+ get: function(inRowIndex){
+ // summary: Default data getter.
+ // description:
+ // Provides data to display in a grid cell. Called in grid cell context.
+ // So this.cell.index is the column index.
+ // inRowIndex: Integer
+ // Row for which to provide data
+ // returns:
+ // Data to display for a given grid cell.
+ },
+
+ // settings
+ // rowCount: Integer
+ // Number of rows to display.
+ rowCount: 5,
+
+ // keepRows: Integer
+ // Number of rows to keep in the rendering cache.
+ keepRows: 75,
+
+ // rowsPerPage: Integer
+ // Number of rows to render at a time.
+ rowsPerPage: 25,
+
+ // autoWidth: Boolean
+ // If autoWidth is true, grid width is automatically set to fit the data.
+ autoWidth: false,
+
+ // autoHeight: Boolean
+ // If autoHeight is true, grid height is automatically set to fit the data.
+ autoHeight: false,
+
+ // autoRender: Boolean
+ // If autoRender is true, grid will render itself after initialization.
+ autoRender: true,
+
+ // defaultHeight: String
+ // default height of the grid, measured in any valid css unit.
+ defaultHeight: '15em',
+
+ // structure: Object|String
+ // View layout defintion. Can be set to a layout object, or to the (string) name of a layout object.
+ structure: '',
+
+ // elasticView: Integer
+ // Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
+ elasticView: -1,
+
+ // singleClickEdit: boolean
+ // Single-click starts editing. Default is double-click
+ singleClickEdit: false,
+
+ // Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
+ _click: null,
+
+ // private
+ sortInfo: 0,
+ themeable: true,
+
+ // initialization
+ buildRendering: function(){
+ this.inherited(arguments);
+ // reset get from blank function (needed for markup parsing) to null, if not changed
+ if(this.get == dojox.VirtualGrid.prototype.get){
+ this.get = null;
+ }
+ if(!this.domNode.getAttribute('tabIndex')){
+ this.domNode.tabIndex = "0";
+ }
+ this.createScroller();
+ this.createLayout();
+ this.createViews();
+ this.createManagers();
+ dojox.grid.initTextSizePoll();
+ this.connect(dojox.grid, "textSizeChanged", "textSizeChanged");
+ dojox.grid.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.keyEvents);
+ this.connect(this, "onShow", "renderOnIdle");
+ },
+ postCreate: function(){
+ // replace stock styleChanged with one that triggers an update
+ this.styleChanged = this._styleChanged;
+ this.setStructure(this.structure);
+ this._click = [];
+ },
+
+ destroy: function(){
+ this.domNode.onReveal = null;
+ this.domNode.onSizeChange = null;
+ this.edit.destroy();
+ this.views.destroyViews();
+ this.inherited(arguments);
+ },
+
+ styleChanged: function(){
+ this.setStyledClass(this.domNode, '');
+ },
+
+ _styleChanged: function(){
+ this.styleChanged();
+ this.update();
+ },
+
+ textSizeChanged: function(){
+ setTimeout(dojo.hitch(this, "_textSizeChanged"), 1);
+ },
+
+ _textSizeChanged: function(){
+ if(this.domNode){
+ this.views.forEach(function(v){
+ v.content.update();
+ });
+ this.render();
+ }
+ },
+
+ sizeChange: function(){
+ dojox.grid.jobs.job(this.id + 'SizeChange', 50, dojo.hitch(this, "update"));
+ },
+
+ renderOnIdle: function() {
+ setTimeout(dojo.hitch(this, "render"), 1);
+ },
+
+ createManagers: function(){
+ // summary:
+ // create grid managers for various tasks including rows, focus, selection, editing
+
+ // row manager
+ this.rows = new dojox.grid.rows(this);
+ // focus manager
+ this.focus = new dojox.grid.focus(this);
+ // selection manager
+ this.selection = new dojox.grid.selection(this);
+ // edit manager
+ this.edit = new dojox.grid.edit(this);
+ },
+
+ createScroller: function(){
+ // summary: Creates a new virtual scroller
+ this.scroller = new dojox.grid.scroller.columns();
+ this.scroller._pageIdPrefix = this.id + '-';
+ this.scroller.renderRow = dojo.hitch(this, "renderRow");
+ this.scroller.removeRow = dojo.hitch(this, "rowRemoved");
+ },
+
+ createLayout: function(){
+ // summary: Creates a new Grid layout
+ this.layout = new dojox.grid.layout(this);
+ },
+
+ // views
+ createViews: function(){
+ this.views = new dojox.grid.views(this);
+ this.views.createView = dojo.hitch(this, "createView");
+ },
+
+ createView: function(inClass){
+ if(dojo.isAIR){
+ var obj = window;
+ var names = inClass.split('.');
+ for(var i=0;i<names.length;i++){
+ if(typeof obj[names[i]]=='undefined'){
+ var undefstring = names[0];
+ for(var j=1;j<=i;j++){
+ undefstring+="."+names[j];
+ }
+ throw new Error(undefstring+" is undefined");
+ }
+ obj = obj[names[i]];
+ }
+ var c = obj;
+ }else{
+ var c = eval(inClass);
+ }
+ var view = new c({ grid: this });
+ this.viewsNode.appendChild(view.domNode);
+ this.viewsHeaderNode.appendChild(view.headerNode);
+ this.views.addView(view);
+ return view;
+ },
+
+ buildViews: function(){
+ for(var i=0, vs; (vs=this.layout.structure[i]); i++){
+ this.createView(vs.type || dojox._scopeName + ".GridView").setStructure(vs);
+ }
+ this.scroller.setContentNodes(this.views.getContentNodes());
+ },
+
+ setStructure: function(inStructure){
+ // summary:
+ // Install a new structure and rebuild the grid.
+ // inStructure: Object
+ // Structure object defines the grid layout and provides various
+ // options for grid views and columns
+ // description:
+ // A grid structure is an array of view objects. A view object can
+ // specify a view type (view class), width, noscroll (boolean flag
+ // for view scrolling), and cells. Cells is an array of objects
+ // corresponding to each grid column. The view cells object is an
+ // array of subrows comprising a single row. Each subrow is an
+ // array of column objects. A column object can have a name,
+ // width, value (default), get function to provide data, styles,
+ // and span attributes (rowSpan, colSpan).
+
+ this.views.destroyViews();
+ this.structure = inStructure;
+ if((this.structure)&&(dojo.isString(this.structure))){
+ this.structure=dojox.grid.getProp(this.structure);
+ }
+ if(!this.structure){
+ this.structure=window["layout"];
+ }
+ if(!this.structure){
+ return;
+ }
+ this.layout.setStructure(this.structure);
+ this._structureChanged();
+ },
+
+ _structureChanged: function() {
+ this.buildViews();
+ if(this.autoRender){
+ this.render();
+ }
+ },
+
+ hasLayout: function() {
+ return this.layout.cells.length;
+ },
+
+ // sizing
+ resize: function(sizeBox){
+ // summary:
+ // Update the grid's rendering dimensions and resize it
+ // sizeBox: Object?
+ // {w: int, h: int, l: int, t: int}
+
+ // FIXME: If grid is not sized explicitly, sometimes bogus scrollbars
+ // can appear in our container, which may require an extra call to 'resize'
+ // to sort out.
+ this._sizeBox = sizeBox;
+ this._resize();
+ this.sizeChange();
+ },
+
+ _getPadBorder: function() {
+ this._padBorder = this._padBorder || dojo._getPadBorderExtents(this.domNode);
+ return this._padBorder;
+ },
+
+ _resize: function(){
+ // if we have set up everything except the DOM, we cannot resize
+ if(!this.domNode.parentNode || this.domNode.parentNode.nodeType != 1 || !this.hasLayout()){
+ return;
+ }
+ // useful measurement
+ var padBorder = this._getPadBorder();
+ // grid height
+ if(this.autoHeight){
+ this.domNode.style.height = 'auto';
+ this.viewsNode.style.height = '';
+ }else if(this.flex > 0){
+ }else if(this.domNode.clientHeight <= padBorder.h){
+ if(this.domNode.parentNode == document.body){
+ this.domNode.style.height = this.defaultHeight;
+ }else{
+ this.fitTo = "parent";
+ }
+ }
+ // if we are given dimensions, size the grid's domNode to those dimensions
+ if(this._sizeBox){
+ dojo.contentBox(this.domNode, this._sizeBox);
+ }else if(this.fitTo == "parent"){
+ var h = dojo._getContentBox(this.domNode.parentNode).h;
+ dojo.marginBox(this.domNode, { h: Math.max(0, h) });
+ }
+
+ var h = dojo._getContentBox(this.domNode).h;
+ if(h == 0 && !this.autoHeight){
+ // We need to hide the header, since the Grid is essentially hidden.
+ this.viewsHeaderNode.style.display = "none";
+ }else{
+ // Otherwise, show the header and give it an appropriate height.
+ this.viewsHeaderNode.style.display = "block";
+ }
+
+ // NOTE: it is essential that width be applied before height
+ // Header height can only be calculated properly after view widths have been set.
+ // This is because flex column width is naturally 0 in Firefox.
+ // Therefore prior to width sizing flex columns with spaces are maximally wrapped
+ // and calculated to be too tall.
+ this.adaptWidth();
+ this.adaptHeight();
+
+ // default row height (FIXME: use running average(?), remove magic #)
+ this.scroller.defaultRowHeight = this.rows.getDefaultHeightPx() + 1;
+ this.postresize();
+ },
+
+ adaptWidth: function() {
+ // private: sets width and position for views and update grid width if necessary
+ var
+ w = this.autoWidth ? 0 : this.domNode.clientWidth || (this.domNode.offsetWidth - this._getPadBorder().w);
+ vw = this.views.arrange(1, w);
+ this.views.onEach("adaptWidth");
+ if (this.autoWidth)
+ this.domNode.style.width = vw + "px";
+ },
+
+ adaptHeight: function(){
+ // private: measures and normalizes header height, then sets view heights, and then updates scroller
+ var vns = this.viewsHeaderNode.style, t = vns.display == "none" ? 0 : this.views.measureHeader();
+ vns.height = t + 'px';
+ // header heights are reset during measuring so must be normalized after measuring.
+ this.views.normalizeHeaderNodeHeight();
+ // content extent
+ var h = (this.autoHeight ? -1 : Math.max(this.domNode.clientHeight - t, 0) || 0);
+ this.views.onEach('setSize', [0, h]);
+ this.views.onEach('adaptHeight');
+ this.scroller.windowHeight = h;
+ },
+
+ // render
+ render: function(){
+ // summary:
+ // Render the grid, headers, and views. Edit and scrolling states are reset. To retain edit and
+ // scrolling states, see Update.
+
+ if(!this.domNode){return;}
+
+ if(!this.hasLayout()) {
+ this.scroller.init(0, this.keepRows, this.rowsPerPage);
+ return;
+ }
+ //
+ this.update = this.defaultUpdate;
+ this.scroller.init(this.rowCount, this.keepRows, this.rowsPerPage);
+ this.prerender();
+ this.setScrollTop(0);
+ this.postrender();
+ },
+
+ prerender: function(){
+ // if autoHeight, make sure scroller knows not to virtualize; everything must be rendered.
+ this.keepRows = this.autoHeight ? 0 : this.constructor.prototype.keepRows;
+ this.scroller.setKeepInfo(this.keepRows);
+ this.views.render();
+ this._resize();
+ },
+
+ postrender: function(){
+ this.postresize();
+ this.focus.initFocusView();
+ // make rows unselectable
+ dojo.setSelectable(this.domNode, false);
+ },
+
+ postresize: function(){
+ // views are position absolute, so they do not inflate the parent
+ if(this.autoHeight){
+ this.viewsNode.style.height = this.views.measureContent() + 'px';
+ }
+ },
+
+ renderRow: function(inRowIndex, inNodes){
+ // summary: private, used internally to render rows
+ this.views.renderRow(inRowIndex, inNodes);
+ },
+
+ rowRemoved: function(inRowIndex){
+ // summary: private, used internally to remove rows
+ this.views.rowRemoved(inRowIndex);
+ },
+
+ invalidated: null,
+
+ updating: false,
+
+ beginUpdate: function(){
+ // summary:
+ // Use to make multiple changes to rows while queueing row updating.
+ // NOTE: not currently supporting nested begin/endUpdate calls
+ this.invalidated = [];
+ this.updating = true;
+ },
+
+ endUpdate: function(){
+ // summary:
+ // Use after calling beginUpdate to render any changes made to rows.
+ this.updating = false;
+ var i = this.invalidated;
+ if(i.all){
+ this.update();
+ }else if(i.rowCount != undefined){
+ this.updateRowCount(i.rowCount);
+ }else{
+ for(r in i){
+ this.updateRow(Number(r));
+ }
+ }
+ this.invalidated = null;
+ },
+
+ // update
+ defaultUpdate: function(){
+ // note: initial update calls render and subsequently this function.
+ if(!this.domNode){return;}
+ if(this.updating){
+ this.invalidated.all = true;
+ return;
+ }
+ //this.edit.saveState(inRowIndex);
+ this.prerender();
+ this.scroller.invalidateNodes();
+ this.setScrollTop(this.scrollTop);
+ this.postrender();
+ //this.edit.restoreState(inRowIndex);
+ },
+
+ update: function(){
+ // summary:
+ // Update the grid, retaining edit and scrolling states.
+ this.render();
+ },
+
+ updateRow: function(inRowIndex){
+ // summary:
+ // Render a single row.
+ // inRowIndex: Integer
+ // Index of the row to render
+ inRowIndex = Number(inRowIndex);
+ if(this.updating){
+ this.invalidated[inRowIndex]=true;
+ }else{
+ this.views.updateRow(inRowIndex, this.rows.getHeight(inRowIndex));
+ this.scroller.rowHeightChanged(inRowIndex);
+ }
+ },
+
+ updateRowCount: function(inRowCount){
+ //summary:
+ // Change the number of rows.
+ // inRowCount: int
+ // Number of rows in the grid.
+ if(this.updating){
+ this.invalidated.rowCount = inRowCount;
+ }else{
+ this.rowCount = inRowCount;
+ if(this.layout.cells.length){
+ this.scroller.updateRowCount(inRowCount);
+ this.setScrollTop(this.scrollTop);
+ }
+ this._resize();
+ }
+ },
+
+ updateRowStyles: function(inRowIndex){
+ // summary:
+ // Update the styles for a row after it's state has changed.
+ this.views.updateRowStyles(inRowIndex);
+ },
+
+ rowHeightChanged: function(inRowIndex){
+ // summary:
+ // Update grid when the height of a row has changed. Row height is handled automatically as rows
+ // are rendered. Use this function only to update a row's height outside the normal rendering process.
+ // inRowIndex: Integer
+ // index of the row that has changed height
+
+ this.views.renormalizeRow(inRowIndex);
+ this.scroller.rowHeightChanged(inRowIndex);
+ },
+
+ // fastScroll: Boolean
+ // flag modifies vertical scrolling behavior. Defaults to true but set to false for slower
+ // scroll performance but more immediate scrolling feedback
+ fastScroll: true,
+
+ delayScroll: false,
+
+ // scrollRedrawThreshold: int
+ // pixel distance a user must scroll vertically to trigger grid scrolling.
+ scrollRedrawThreshold: (dojo.isIE ? 100 : 50),
+
+ // scroll methods
+ scrollTo: function(inTop){
+ // summary:
+ // Vertically scroll the grid to a given pixel position
+ // inTop: Integer
+ // vertical position of the grid in pixels
+ if(!this.fastScroll){
+ this.setScrollTop(inTop);
+ return;
+ }
+ var delta = Math.abs(this.lastScrollTop - inTop);
+ this.lastScrollTop = inTop;
+ if(delta > this.scrollRedrawThreshold || this.delayScroll){
+ this.delayScroll = true;
+ this.scrollTop = inTop;
+ this.views.setScrollTop(inTop);
+ dojox.grid.jobs.job('dojoxGrid-scroll', 200, dojo.hitch(this, "finishScrollJob"));
+ }else{
+ this.setScrollTop(inTop);
+ }
+ },
+
+ finishScrollJob: function(){
+ this.delayScroll = false;
+ this.setScrollTop(this.scrollTop);
+ },
+
+ setScrollTop: function(inTop){
+ this.scrollTop = this.views.setScrollTop(inTop);
+ this.scroller.scroll(this.scrollTop);
+ },
+
+ scrollToRow: function(inRowIndex){
+ // summary:
+ // Scroll the grid to a specific row.
+ // inRowIndex: Integer
+ // grid row index
+ this.setScrollTop(this.scroller.findScrollTop(inRowIndex) + 1);
+ },
+
+ // styling (private, used internally to style individual parts of a row)
+ styleRowNode: function(inRowIndex, inRowNode){
+ if(inRowNode){
+ this.rows.styleRowNode(inRowIndex, inRowNode);
+ }
+ },
+
+ // cells
+ getCell: function(inIndex){
+ // summary:
+ // Retrieves the cell object for a given grid column.
+ // inIndex: Integer
+ // Grid column index of cell to retrieve
+ // returns:
+ // a grid cell
+ return this.layout.cells[inIndex];
+ },
+
+ setCellWidth: function(inIndex, inUnitWidth) {
+ this.getCell(inIndex).unitWidth = inUnitWidth;
+ },
+
+ getCellName: function(inCell){
+ // summary: Returns the cell name of a passed cell
+ return "Cell " + inCell.index; // String
+ },
+
+ // sorting
+ canSort: function(inSortInfo){
+ // summary:
+ // Determines if the grid can be sorted
+ // inSortInfo: Integer
+ // Sort information, 1-based index of column on which to sort, positive for an ascending sort
+ // and negative for a descending sort
+ // returns: Boolean
+ // True if grid can be sorted on the given column in the given direction
+ },
+
+ sort: function(){
+ },
+
+ getSortAsc: function(inSortInfo){
+ // summary:
+ // Returns true if grid is sorted in an ascending direction.
+ inSortInfo = inSortInfo == undefined ? this.sortInfo : inSortInfo;
+ return Boolean(inSortInfo > 0); // Boolean
+ },
+
+ getSortIndex: function(inSortInfo){
+ // summary:
+ // Returns the index of the column on which the grid is sorted
+ inSortInfo = inSortInfo == undefined ? this.sortInfo : inSortInfo;
+ return Math.abs(inSortInfo) - 1; // Integer
+ },
+
+ setSortIndex: function(inIndex, inAsc){
+ // summary:
+ // Sort the grid on a column in a specified direction
+ // inIndex: Integer
+ // Column index on which to sort.
+ // inAsc: Boolean
+ // If true, sort the grid in ascending order, otherwise in descending order
+ var si = inIndex +1;
+ if(inAsc != undefined){
+ si *= (inAsc ? 1 : -1);
+ } else if(this.getSortIndex() == inIndex){
+ si = -this.sortInfo;
+ }
+ this.setSortInfo(si);
+ },
+
+ setSortInfo: function(inSortInfo){
+ if(this.canSort(inSortInfo)){
+ this.sortInfo = inSortInfo;
+ this.sort();
+ this.update();
+ }
+ },
+
+ // DOM event handler
+ doKeyEvent: function(e){
+ e.dispatch = 'do' + e.type;
+ this.onKeyEvent(e);
+ },
+
+ // event dispatch
+ //: protected
+ _dispatch: function(m, e){
+ if(m in this){
+ return this[m](e);
+ }
+ },
+
+ dispatchKeyEvent: function(e){
+ this._dispatch(e.dispatch, e);
+ },
+
+ dispatchContentEvent: function(e){
+ this.edit.dispatchEvent(e) || e.sourceView.dispatchContentEvent(e) || this._dispatch(e.dispatch, e);
+ },
+
+ dispatchHeaderEvent: function(e){
+ e.sourceView.dispatchHeaderEvent(e) || this._dispatch('doheader' + e.type, e);
+ },
+
+ dokeydown: function(e){
+ this.onKeyDown(e);
+ },
+
+ doclick: function(e){
+ if(e.cellNode){
+ this.onCellClick(e);
+ }else{
+ this.onRowClick(e);
+ }
+ },
+
+ dodblclick: function(e){
+ if(e.cellNode){
+ this.onCellDblClick(e);
+ }else{
+ this.onRowDblClick(e);
+ }
+ },
+
+ docontextmenu: function(e){
+ if(e.cellNode){
+ this.onCellContextMenu(e);
+ }else{
+ this.onRowContextMenu(e);
+ }
+ },
+
+ doheaderclick: function(e){
+ if(e.cellNode){
+ this.onHeaderCellClick(e);
+ }else{
+ this.onHeaderClick(e);
+ }
+ },
+
+ doheaderdblclick: function(e){
+ if(e.cellNode){
+ this.onHeaderCellDblClick(e);
+ }else{
+ this.onHeaderDblClick(e);
+ }
+ },
+
+ doheadercontextmenu: function(e){
+ if(e.cellNode){
+ this.onHeaderCellContextMenu(e);
+ }else{
+ this.onHeaderContextMenu(e);
+ }
+ },
+
+ // override to modify editing process
+ doStartEdit: function(inCell, inRowIndex){
+ this.onStartEdit(inCell, inRowIndex);
+ },
+
+ doApplyCellEdit: function(inValue, inRowIndex, inFieldIndex){
+ this.onApplyCellEdit(inValue, inRowIndex, inFieldIndex);
+ },
+
+ doCancelEdit: function(inRowIndex){
+ this.onCancelEdit(inRowIndex);
+ },
+
+ doApplyEdit: function(inRowIndex){
+ this.onApplyEdit(inRowIndex);
+ },
+
+ // row editing
+ addRow: function(){
+ // summary:
+ // Add a row to the grid.
+ this.updateRowCount(this.rowCount+1);
+ },
+
+ removeSelectedRows: function(){
+ // summary:
+ // Remove the selected rows from the grid.
+ this.updateRowCount(Math.max(0, this.rowCount - this.selection.getSelected().length));
+ this.selection.clear();
+ }
+
+});
+
+dojo.mixin(dojox.VirtualGrid.prototype, dojox.grid.publicEvents);
+
+}
diff --git a/includes/js/dojox/grid/_data/dijitEditors.js b/includes/js/dojox/grid/_data/dijitEditors.js
new file mode 100644
index 0000000..695de44
--- /dev/null
+++ b/includes/js/dojox/grid/_data/dijitEditors.js
@@ -0,0 +1,170 @@
+if(!dojo._hasResource["dojox.grid._data.dijitEditors"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._data.dijitEditors"] = true;
+dojo.provide("dojox.grid._data.dijitEditors");
+dojo.require("dojox.grid._data.editors");
+dojo.require("dijit.form.DateTextBox");
+dojo.require("dijit.form.TimeTextBox");
+dojo.require("dijit.form.ComboBox");
+dojo.require("dojo.data.ItemFileReadStore");
+dojo.require("dijit.form.CheckBox");
+dojo.require("dijit.form.TextBox");
+dojo.require("dijit.form.NumberSpinner");
+dojo.require("dijit.form.NumberTextBox");
+dojo.require("dijit.form.CurrencyTextBox");
+dojo.require("dijit.form.Slider");
+dojo.require("dijit.Editor");
+
+dojo.declare("dojox.grid.editors.Dijit", dojox.grid.editors.base, {
+ editorClass: "dijit.form.TextBox",
+ constructor: function(inCell){
+ this.editor = null;
+ this.editorClass = dojo.getObject(this.cell.editorClass || this.editorClass);
+ },
+ format: function(inDatum, inRowIndex){
+ this.needFormatNode(inDatum, inRowIndex);
+ return "<div></div>";
+ },
+ getValue: function(inRowIndex){
+ return this.editor.getValue();
+ },
+ setValue: function(inRowIndex, inValue){
+ if(this.editor&&this.editor.setValue){
+ this.editor.setValue(inValue);
+ }else{
+ this.inherited(arguments);
+ }
+ },
+ getEditorProps: function(inDatum){
+ return dojo.mixin({}, this.cell.editorProps||{}, {
+ constraints: dojo.mixin({}, this.cell.constraint) || {}, //TODO: really just for ValidationTextBoxes
+ value: inDatum
+ });
+ },
+ createEditor: function(inNode, inDatum, inRowIndex){
+ return new this.editorClass(this.getEditorProps(inDatum), inNode);
+
+ },
+ attachEditor: function(inNode, inDatum, inRowIndex){
+ inNode.appendChild(this.editor.domNode);
+ this.setValue(inRowIndex, inDatum);
+ },
+ formatNode: function(inNode, inDatum, inRowIndex){
+ if(!this.editorClass){
+ return inDatum;
+ }
+ if(!this.editor){
+ this.editor = this.createEditor.apply(this, arguments);
+ }else{
+ this.attachEditor.apply(this, arguments);
+ }
+ this.sizeEditor.apply(this, arguments);
+ this.cell.grid.rowHeightChanged(inRowIndex);
+ this.focus();
+ },
+ sizeEditor: function(inNode, inDatum, inRowIndex){
+ var
+ p = this.cell.getNode(inRowIndex),
+ box = dojo.contentBox(p);
+ dojo.marginBox(this.editor.domNode, {w: box.w});
+ },
+ focus: function(inRowIndex, inNode){
+ if(this.editor){
+ setTimeout(dojo.hitch(this.editor, function(){
+ dojox.grid.fire(this, "focus");
+ }), 0);
+ }
+ },
+ _finish: function(inRowIndex){
+ this.inherited(arguments);
+ dojox.grid.removeNode(this.editor.domNode);
+ }
+});
+
+dojo.declare("dojox.grid.editors.ComboBox", dojox.grid.editors.Dijit, {
+ editorClass: "dijit.form.ComboBox",
+ getEditorProps: function(inDatum){
+ var items=[];
+ dojo.forEach(this.cell.options, function(o){
+ items.push({name: o, value: o});
+ });
+ var store = new dojo.data.ItemFileReadStore({data: {identifier:"name", items: items}});
+ return dojo.mixin({}, this.cell.editorProps||{}, {
+ value: inDatum,
+ store: store
+ });
+ },
+ getValue: function(){
+ var e = this.editor;
+ // make sure to apply the displayed value
+ e.setDisplayedValue(e.getDisplayedValue());
+ return e.getValue();
+ }
+});
+
+dojo.declare("dojox.grid.editors.DateTextBox", dojox.grid.editors.Dijit, {
+ editorClass: "dijit.form.DateTextBox",
+ setValue: function(inRowIndex, inValue){
+ if(this.editor){
+ this.editor.setValue(new Date(inValue));
+ }else{
+ this.inherited(arguments);
+ }
+ },
+ getEditorProps: function(inDatum){
+ return dojo.mixin(this.inherited(arguments), {
+ value: new Date(inDatum)
+ });
+ }
+});
+
+
+dojo.declare("dojox.grid.editors.CheckBox", dojox.grid.editors.Dijit, {
+ editorClass: "dijit.form.CheckBox",
+ getValue: function(){
+ return this.editor.checked;
+ },
+ setValue: function(inRowIndex, inValue){
+ if(this.editor&&this.editor.setAttribute){
+ this.editor.setAttribute("checked", inValue);
+ }else{
+ this.inherited(arguments);
+ }
+ },
+ sizeEditor: function(inNode, inDatum, inRowIndex){
+ return;
+ }
+});
+
+
+dojo.declare("dojox.grid.editors.Editor", dojox.grid.editors.Dijit, {
+ editorClass: "dijit.Editor",
+ getEditorProps: function(inDatum){
+ return dojo.mixin({}, this.cell.editorProps||{}, {
+ height: this.cell.editorHeight || "100px"
+ });
+ },
+ createEditor: function(inNode, inDatum, inRowIndex){
+ // editor needs its value set after creation
+ var editor = new this.editorClass(this.getEditorProps(inDatum), inNode);
+ dojo.connect(editor, 'onLoad', dojo.hitch(this, 'populateEditor'));
+ return editor;
+ },
+ formatNode: function(inNode, inDatum, inRowIndex){
+ this.content = inDatum;
+ this.inherited(arguments);
+ if(dojo.isMoz){
+ // FIXME: seem to need to reopen the editor and display the toolbar
+ var e = this.editor;
+ e.open();
+ if(this.cell.editorToolbar){
+ dojo.place(e.toolbar.domNode, e.editingArea, "before");
+ }
+ }
+ },
+ populateEditor: function(){
+ this.editor.setValue(this.content);
+ this.editor.placeCursorAtEnd();
+ }
+});
+
+}
diff --git a/includes/js/dojox/grid/_data/editors.js b/includes/js/dojox/grid/_data/editors.js
new file mode 100644
index 0000000..48f76cc
--- /dev/null
+++ b/includes/js/dojox/grid/_data/editors.js
@@ -0,0 +1,239 @@
+if(!dojo._hasResource["dojox.grid._data.editors"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._data.editors"] = true;
+dojo.provide("dojox.grid._data.editors");
+dojo.provide("dojox.grid.editors");
+
+dojo.declare("dojox.grid.editors.Base", null, {
+ // summary:
+ // base grid editor class. Other grid editors should inherited from this class.
+ constructor: function(inCell){
+ this.cell = inCell;
+ },
+ //private
+ _valueProp: "value",
+ _formatPending: false,
+ format: function(inDatum, inRowIndex){
+ // summary:
+ // formats the cell for editing
+ // inDatum: anything
+ // cell data to edit
+ // inRowIndex: int
+ // grid row index
+ // returns: string of html to place in grid cell
+ },
+ //protected
+ needFormatNode: function(inDatum, inRowIndex){
+ this._formatPending = true;
+ dojox.grid.whenIdle(this, "_formatNode", inDatum, inRowIndex);
+ },
+ cancelFormatNode: function(){
+ this._formatPending = false;
+ },
+ //private
+ _formatNode: function(inDatum, inRowIndex){
+ if(this._formatPending){
+ this._formatPending = false;
+ // make cell selectable
+ dojo.setSelectable(this.cell.grid.domNode, true);
+ this.formatNode(this.getNode(inRowIndex), inDatum, inRowIndex);
+ }
+ },
+ //protected
+ getNode: function(inRowIndex){
+ return (this.cell.getNode(inRowIndex) || 0).firstChild || 0;
+ },
+ formatNode: function(inNode, inDatum, inRowIndex){
+ // summary:
+ // format the editing dom node. Use when editor is a widget.
+ // inNode: dom node
+ // dom node for the editor
+ // inDatum: anything
+ // cell data to edit
+ // inRowIndex: int
+ // grid row index
+ if(dojo.isIE){
+ // IE sux bad
+ dojox.grid.whenIdle(this, "focus", inRowIndex, inNode);
+ }else{
+ this.focus(inRowIndex, inNode);
+ }
+ },
+ dispatchEvent: function(m, e){
+ if(m in this){
+ return this[m](e);
+ }
+ },
+ //public
+ getValue: function(inRowIndex){
+ // summary:
+ // returns value entered into editor
+ // inRowIndex: int
+ // grid row index
+ // returns:
+ // value of editor
+ return this.getNode(inRowIndex)[this._valueProp];
+ },
+ setValue: function(inRowIndex, inValue){
+ // summary:
+ // set the value of the grid editor
+ // inRowIndex: int
+ // grid row index
+ // inValue: anything
+ // value of editor
+ var n = this.getNode(inRowIndex);
+ if(n){
+ n[this._valueProp] = inValue
+ };
+ },
+ focus: function(inRowIndex, inNode){
+ // summary:
+ // focus the grid editor
+ // inRowIndex: int
+ // grid row index
+ // inNode: dom node
+ // editor node
+ dojox.grid.focusSelectNode(inNode || this.getNode(inRowIndex));
+ },
+ save: function(inRowIndex){
+ // summary:
+ // save editor state
+ // inRowIndex: int
+ // grid row index
+ this.value = this.value || this.getValue(inRowIndex);
+ //console.log("save", this.value, inCell.index, inRowIndex);
+ },
+ restore: function(inRowIndex){
+ // summary:
+ // restore editor state
+ // inRowIndex: int
+ // grid row index
+ this.setValue(inRowIndex, this.value);
+ //console.log("restore", this.value, inCell.index, inRowIndex);
+ },
+ //protected
+ _finish: function(inRowIndex){
+ // summary:
+ // called when editing is completed to clean up editor
+ // inRowIndex: int
+ // grid row index
+ dojo.setSelectable(this.cell.grid.domNode, false);
+ this.cancelFormatNode(this.cell);
+ },
+ //public
+ apply: function(inRowIndex){
+ // summary:
+ // apply edit from cell editor
+ // inRowIndex: int
+ // grid row index
+ this.cell.applyEdit(this.getValue(inRowIndex), inRowIndex);
+ this._finish(inRowIndex);
+ },
+ cancel: function(inRowIndex){
+ // summary:
+ // cancel cell edit
+ // inRowIndex: int
+ // grid row index
+ this.cell.cancelEdit(inRowIndex);
+ this._finish(inRowIndex);
+ }
+});
+dojox.grid.editors.base = dojox.grid.editors.Base; // back-compat
+
+dojo.declare("dojox.grid.editors.Input", dojox.grid.editors.Base, {
+ // summary
+ // grid cell editor that provides a standard text input box
+ constructor: function(inCell){
+ this.keyFilter = this.keyFilter || this.cell.keyFilter;
+ },
+ // keyFilter: object
+ // optional regex for disallowing keypresses
+ keyFilter: null,
+ format: function(inDatum, inRowIndex){
+ this.needFormatNode(inDatum, inRowIndex);
+ return '<input class="dojoxGrid-input" type="text" value="' + inDatum + '">';
+ },
+ formatNode: function(inNode, inDatum, inRowIndex){
+ this.inherited(arguments);
+ // FIXME: feels too specific for this interface
+ this.cell.registerOnBlur(inNode, inRowIndex);
+ },
+ doKey: function(e){
+ if(this.keyFilter){
+ var key = String.fromCharCode(e.charCode);
+ if(key.search(this.keyFilter) == -1){
+ dojo.stopEvent(e);
+ }
+ }
+ },
+ _finish: function(inRowIndex){
+ this.inherited(arguments);
+ var n = this.getNode(inRowIndex);
+ try{
+ dojox.grid.fire(n, "blur");
+ }catch(e){}
+ }
+});
+dojox.grid.editors.input = dojox.grid.editors.Input; // back compat
+
+dojo.declare("dojox.grid.editors.Select", dojox.grid.editors.Input, {
+ // summary:
+ // grid cell editor that provides a standard select
+ // options: text of each item
+ // values: value for each item
+ // returnIndex: editor returns only the index of the selected option and not the value
+ constructor: function(inCell){
+ this.options = this.options || this.cell.options;
+ this.values = this.values || this.cell.values || this.options;
+ },
+ format: function(inDatum, inRowIndex){
+ this.needFormatNode(inDatum, inRowIndex);
+ var h = [ '<select class="dojoxGrid-select">' ];
+ for (var i=0, o, v; ((o=this.options[i]) !== undefined)&&((v=this.values[i]) !== undefined); i++){
+ h.push("<option", (inDatum==v ? ' selected' : ''), ' value="' + v + '"', ">", o, "</option>");
+ }
+ h.push('</select>');
+ return h.join('');
+ },
+ getValue: function(inRowIndex){
+ var n = this.getNode(inRowIndex);
+ if(n){
+ var i = n.selectedIndex, o = n.options[i];
+ return this.cell.returnIndex ? i : o.value || o.innerHTML;
+ }
+ }
+});
+dojox.grid.editors.select = dojox.grid.editors.Select; // back compat
+
+dojo.declare("dojox.grid.editors.AlwaysOn", dojox.grid.editors.Input, {
+ // summary:
+ // grid cell editor that is always on, regardless of grid editing state
+ // alwaysOn: boolean
+ // flag to use editor to format grid cell regardless of editing state.
+ alwaysOn: true,
+ _formatNode: function(inDatum, inRowIndex){
+ this.formatNode(this.getNode(inRowIndex), inDatum, inRowIndex);
+ },
+ applyStaticValue: function(inRowIndex){
+ var e = this.cell.grid.edit;
+ e.applyCellEdit(this.getValue(inRowIndex), this.cell, inRowIndex);
+ e.start(this.cell, inRowIndex, true);
+ }
+});
+dojox.grid.editors.alwaysOn = dojox.grid.editors.AlwaysOn; // back-compat
+
+dojo.declare("dojox.grid.editors.Bool", dojox.grid.editors.AlwaysOn, {
+ // summary:
+ // grid cell editor that provides a standard checkbox that is always on
+ _valueProp: "checked",
+ format: function(inDatum, inRowIndex){
+ return '<input class="dojoxGrid-input" type="checkbox"' + (inDatum ? ' checked="checked"' : '') + ' style="width: auto" />';
+ },
+ doclick: function(e){
+ if(e.target.tagName == 'INPUT'){
+ this.applyStaticValue(e.rowIndex);
+ }
+ }
+});
+dojox.grid.editors.bool = dojox.grid.editors.Bool; // back-compat
+
+}
diff --git a/includes/js/dojox/grid/_data/fields.js b/includes/js/dojox/grid/_data/fields.js
new file mode 100644
index 0000000..230bede
--- /dev/null
+++ b/includes/js/dojox/grid/_data/fields.js
@@ -0,0 +1,104 @@
+if(!dojo._hasResource["dojox.grid._data.fields"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._data.fields"] = true;
+dojo.provide("dojox.grid._data.fields");
+
+dojo.declare("dojox.grid.data.Mixer", null, {
+ // summary:
+ // basic collection class that provides a default value for items
+
+ constructor: function(){
+ this.defaultValue = {};
+ this.values = [];
+ },
+ count: function(){
+ return this.values.length;
+ },
+ clear: function(){
+ this.values = [];
+ },
+ build: function(inIndex){
+ var result = dojo.mixin({owner: this}, this.defaultValue);
+ result.key = inIndex;
+ this.values[inIndex] = result;
+ return result;
+ },
+ getDefault: function(){
+ return this.defaultValue;
+ },
+ setDefault: function(inField /*[, inField2, ... inFieldN] */){
+ for(var i=0, a; (a = arguments[i]); i++){
+ dojo.mixin(this.defaultValue, a);
+ }
+ },
+ get: function(inIndex){
+ return this.values[inIndex] || this.build(inIndex);
+ },
+ _set: function(inIndex, inField /*[, inField2, ... inFieldN] */){
+ // each field argument can be a single field object of an array of field objects
+ var v = this.get(inIndex);
+ for(var i=1; i<arguments.length; i++){
+ dojo.mixin(v, arguments[i]);
+ }
+ this.values[inIndex] = v;
+ },
+ set: function(/* inIndex, inField [, inField2, ... inFieldN] | inArray */){
+ if(arguments.length < 1){
+ return;
+ }
+ var a = arguments[0];
+ if(!dojo.isArray(a)){
+ this._set.apply(this, arguments);
+ }else{
+ if(a.length && a[0]["default"]){
+ this.setDefault(a.shift());
+ }
+ for(var i=0, l=a.length; i<l; i++){
+ this._set(i, a[i]);
+ }
+ }
+ },
+ insert: function(inIndex, inProps){
+ if (inIndex >= this.values.length){
+ this.values[inIndex] = inProps;
+ }else{
+ this.values.splice(inIndex, 0, inProps);
+ }
+ },
+ remove: function(inIndex){
+ this.values.splice(inIndex, 1);
+ },
+ swap: function(inIndexA, inIndexB){
+ dojox.grid.arraySwap(this.values, inIndexA, inIndexB);
+ },
+ move: function(inFromIndex, inToIndex){
+ dojox.grid.arrayMove(this.values, inFromIndex, inToIndex);
+ }
+});
+
+dojox.grid.data.compare = function(a, b){
+ return (a > b ? 1 : (a == b ? 0 : -1));
+}
+
+dojo.declare('dojox.grid.data.Field', null, {
+ constructor: function(inName){
+ this.name = inName;
+ this.compare = dojox.grid.data.compare;
+ },
+ na: dojox.grid.na
+});
+
+dojo.declare('dojox.grid.data.Fields', dojox.grid.data.Mixer, {
+ constructor: function(inFieldClass){
+ var fieldClass = inFieldClass ? inFieldClass : dojox.grid.data.Field;
+ this.defaultValue = new fieldClass();
+ },
+ indexOf: function(inKey){
+ for(var i=0; i<this.values.length; i++){
+ var v = this.values[i];
+ if(v && v.key == inKey){return i;}
+ }
+ return -1;
+ }
+});
+
+}
diff --git a/includes/js/dojox/grid/_data/model.js b/includes/js/dojox/grid/_data/model.js
new file mode 100644
index 0000000..c9bfcfa
--- /dev/null
+++ b/includes/js/dojox/grid/_data/model.js
@@ -0,0 +1,762 @@
+if(!dojo._hasResource['dojox.grid._data.model']){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource['dojox.grid._data.model'] = true;
+dojo.provide('dojox.grid._data.model');
+dojo.require('dojox.grid._data.fields');
+
+dojo.declare("dojox.grid.data.Model", null, {
+ // summary:
+ // Base abstract grid data model.
+ // Makes no assumptions about the structure of grid data.
+ constructor: function(inFields, inData){
+ this.observers = [];
+ this.fields = new dojox.grid.data.Fields();
+ if(inFields){
+ this.fields.set(inFields);
+ }
+ this.setData(inData);
+ },
+ count: 0,
+ updating: 0,
+ // observers
+ observer: function(inObserver, inPrefix){
+ this.observers.push({o: inObserver, p: inPrefix||'model' });
+ },
+ notObserver: function(inObserver){
+ for(var i=0, m, o; (o=this.observers[i]); i++){
+ if(o.o==inObserver){
+ this.observers.splice(i, 1);
+ return;
+ }
+ }
+ },
+ notify: function(inMsg, inArgs){
+ if(!this.isUpdating()){
+ var a = inArgs || [];
+ for(var i=0, m, o; (o=this.observers[i]); i++){
+ m = o.p + inMsg; o = o.o;
+ (m in o)&&(o[m].apply(o, a));
+ }
+ }
+ },
+ // updates
+ clear: function(){
+ this.fields.clear();
+ this.clearData();
+ },
+ beginUpdate: function(){
+ this.updating++;
+ },
+ endUpdate: function(){
+ if(this.updating){
+ this.updating--;
+ }
+ /*if(this.updating){
+ if(!(--this.updating)){
+ this.change();
+ }
+ }
+ }*/
+ },
+ isUpdating: function(){
+ return Boolean(this.updating);
+ },
+ // data
+ clearData: function(){
+ this.setData(null);
+ },
+ // observer events
+ change: function(){
+ this.notify("Change", arguments);
+ },
+ insertion: function(/* index */){
+ this.notify("Insertion", arguments);
+ this.notify("Change", arguments);
+ },
+ removal: function(/* keys */){
+ this.notify("Removal", arguments);
+ this.notify("Change", arguments);
+ },
+ // insert
+ insert: function(inData /*, index */){
+ if(!this._insert.apply(this, arguments)){
+ return false;
+ }
+ this.insertion.apply(this, dojo._toArray(arguments, 1));
+ return true;
+ },
+ // remove
+ remove: function(inData /*, index */){
+ if(!this._remove.apply(this, arguments)){
+ return false;
+ }
+ this.removal.apply(this, arguments);
+ return true;
+ },
+ // sort
+ canSort: function(/* (+|-)column_index+1, ... */){
+ return this.sort != null;
+ },
+ generateComparator: function(inCompare, inField, inTrueForAscend, inSubCompare){
+ return function(a, b){
+ var ineq = inCompare(a[inField], b[inField]);
+ return ineq ? (inTrueForAscend ? ineq : -ineq) : inSubCompare && inSubCompare(a, b);
+ }
+ },
+ makeComparator: function(inIndices){
+ var idx, col, field, result = null;
+ for(var i=inIndices.length-1; i>=0; i--){
+ idx = inIndices[i];
+ col = Math.abs(idx) - 1;
+ if(col >= 0){
+ field = this.fields.get(col);
+ result = this.generateComparator(field.compare, field.key, idx > 0, result);
+ }
+ }
+ return result;
+ },
+ sort: null,
+ dummy: 0
+});
+
+dojo.declare("dojox.grid.data.Rows", dojox.grid.data.Model, {
+ // observer events
+ allChange: function(){
+ this.notify("AllChange", arguments);
+ this.notify("Change", arguments);
+ },
+ rowChange: function(){
+ this.notify("RowChange", arguments);
+ },
+ datumChange: function(){
+ this.notify("DatumChange", arguments);
+ },
+ // copyRow: function(inRowIndex); // abstract
+ // update
+ beginModifyRow: function(inRowIndex){
+ if(!this.cache[inRowIndex]){
+ this.cache[inRowIndex] = this.copyRow(inRowIndex);
+ }
+ },
+ endModifyRow: function(inRowIndex){
+ var cache = this.cache[inRowIndex];
+ if(cache){
+ var data = this.getRow(inRowIndex);
+ if(!dojox.grid.arrayCompare(cache, data)){
+ this.update(cache, data, inRowIndex);
+ }
+ delete this.cache[inRowIndex];
+ }
+ },
+ cancelModifyRow: function(inRowIndex){
+ var cache = this.cache[inRowIndex];
+ if(cache){
+ this.setRow(cache, inRowIndex);
+ delete this.cache[inRowIndex];
+ }
+ }
+});
+
+dojo.declare("dojox.grid.data.Table", dojox.grid.data.Rows, {
+ // summary:
+ // Basic grid data model for static data in the form of an array of rows
+ // that are arrays of cell data
+ constructor: function(){
+ this.cache = [];
+ },
+ colCount: 0, // tables introduce cols
+ data: null,
+ cache: null,
+ // morphology
+ measure: function(){
+ this.count = this.getRowCount();
+ this.colCount = this.getColCount();
+ this.allChange();
+ //this.notify("Measure");
+ },
+ getRowCount: function(){
+ return (this.data ? this.data.length : 0);
+ },
+ getColCount: function(){
+ return (this.data && this.data.length ? this.data[0].length : this.fields.count());
+ },
+ badIndex: function(inCaller, inDescriptor){
+ console.debug('dojox.grid.data.Table: badIndex');
+ },
+ isGoodIndex: function(inRowIndex, inColIndex){
+ return (inRowIndex >= 0 && inRowIndex < this.count && (arguments.length < 2 || (inColIndex >= 0 && inColIndex < this.colCount)));
+ },
+ // access
+ getRow: function(inRowIndex){
+ return this.data[inRowIndex];
+ },
+ copyRow: function(inRowIndex){
+ return this.getRow(inRowIndex).slice(0);
+ },
+ getDatum: function(inRowIndex, inColIndex){
+ return this.data[inRowIndex][inColIndex];
+ },
+ get: function(){
+ throw('Plain "get" no longer supported. Use "getRow" or "getDatum".');
+ },
+ setData: function(inData){
+ this.data = (inData || []);
+ this.allChange();
+ },
+ setRow: function(inData, inRowIndex){
+ this.data[inRowIndex] = inData;
+ this.rowChange(inData, inRowIndex);
+ this.change();
+ },
+ setDatum: function(inDatum, inRowIndex, inColIndex){
+ this.data[inRowIndex][inColIndex] = inDatum;
+ this.datumChange(inDatum, inRowIndex, inColIndex);
+ },
+ set: function(){
+ throw('Plain "set" no longer supported. Use "setData", "setRow", or "setDatum".');
+ },
+ setRows: function(inData, inRowIndex){
+ for(var i=0, l=inData.length, r=inRowIndex; i<l; i++, r++){
+ this.setRow(inData[i], r);
+ }
+ },
+ // update
+ update: function(inOldData, inNewData, inRowIndex){
+ //delete this.cache[inRowIndex];
+ //this.setRow(inNewData, inRowIndex);
+ return true;
+ },
+ // insert
+ _insert: function(inData, inRowIndex){
+ dojox.grid.arrayInsert(this.data, inRowIndex, inData);
+ this.count++;
+ return true;
+ },
+ // remove
+ _remove: function(inKeys){
+ for(var i=inKeys.length-1; i>=0; i--){
+ dojox.grid.arrayRemove(this.data, inKeys[i]);
+ }
+ this.count -= inKeys.length;
+ return true;
+ },
+ // sort
+ sort: function(/* (+|-)column_index+1, ... */){
+ this.data.sort(this.makeComparator(arguments));
+ },
+ swap: function(inIndexA, inIndexB){
+ dojox.grid.arraySwap(this.data, inIndexA, inIndexB);
+ this.rowChange(this.getRow(inIndexA), inIndexA);
+ this.rowChange(this.getRow(inIndexB), inIndexB);
+ this.change();
+ },
+ dummy: 0
+});
+
+dojo.declare("dojox.grid.data.Objects", dojox.grid.data.Table, {
+ constructor: function(inFields, inData, inKey){
+ if(!inFields){
+ this.autoAssignFields();
+ }
+ },
+ allChange: function(){
+ this.notify("FieldsChange");
+ this.inherited(arguments);
+ },
+ autoAssignFields: function(){
+ var d = this.data[0], i = 0, field;
+ for(var f in d){
+ field = this.fields.get(i++);
+ if (!dojo.isString(field.key)){
+ field.key = f;
+ }
+ }
+ },
+ setData: function(inData){
+ this.data = (inData || []);
+ this.autoAssignFields();
+ this.allChange();
+ },
+ getDatum: function(inRowIndex, inColIndex){
+ return this.data[inRowIndex][this.fields.get(inColIndex).key];
+ }
+});
+
+dojo.declare("dojox.grid.data.Dynamic", dojox.grid.data.Table, {
+ // summary:
+ // Grid data model for dynamic data such as data retrieved from a server.
+ // Retrieves data automatically when requested and provides notification when data is received
+ constructor: function(){
+ this.page = [];
+ this.pages = [];
+ },
+ page: null,
+ pages: null,
+ rowsPerPage: 100,
+ requests: 0,
+ bop: -1,
+ eop: -1,
+ // data
+ clearData: function(){
+ this.pages = [];
+ this.bop = this.eop = -1;
+ this.setData([]);
+ },
+ getRowCount: function(){
+ return this.count;
+ },
+ getColCount: function(){
+ return this.fields.count();
+ },
+ setRowCount: function(inCount){
+ this.count = inCount;
+ this.change();
+ },
+ // paging
+ requestsPending: function(inBoolean){
+ },
+ rowToPage: function(inRowIndex){
+ return (this.rowsPerPage ? Math.floor(inRowIndex / this.rowsPerPage) : inRowIndex);
+ },
+ pageToRow: function(inPageIndex){
+ return (this.rowsPerPage ? this.rowsPerPage * inPageIndex : inPageIndex);
+ },
+ requestRows: function(inRowIndex, inCount){
+ // summary:
+ // stub. Fill in to perform actual data row fetching logic. The
+ // returning logic must provide the data back to the system via
+ // setRow
+ },
+ rowsProvided: function(inRowIndex, inCount){
+ this.requests--;
+ if(this.requests == 0){
+ this.requestsPending(false);
+ }
+ },
+ requestPage: function(inPageIndex){
+ var row = this.pageToRow(inPageIndex);
+ var count = Math.min(this.rowsPerPage, this.count - row);
+ if(count > 0){
+ this.requests++;
+ this.requestsPending(true);
+ setTimeout(dojo.hitch(this, "requestRows", row, count), 1);
+ //this.requestRows(row, count);
+ }
+ },
+ needPage: function(inPageIndex){
+ if(!this.pages[inPageIndex]){
+ this.pages[inPageIndex] = true;
+ this.requestPage(inPageIndex);
+ }
+ },
+ preparePage: function(inRowIndex, inColIndex){
+ if(inRowIndex < this.bop || inRowIndex >= this.eop){
+ var pageIndex = this.rowToPage(inRowIndex);
+ this.needPage(pageIndex);
+ this.bop = pageIndex * this.rowsPerPage;
+ this.eop = this.bop + (this.rowsPerPage || this.count);
+ }
+ },
+ isRowLoaded: function(inRowIndex){
+ return Boolean(this.data[inRowIndex]);
+ },
+ // removal
+ removePages: function(inRowIndexes){
+ for(var i=0, r; ((r=inRowIndexes[i]) != undefined); i++){
+ this.pages[this.rowToPage(r)] = false;
+ }
+ this.bop = this.eop =-1;
+ },
+ remove: function(inRowIndexes){
+ this.removePages(inRowIndexes);
+ dojox.grid.data.Table.prototype.remove.apply(this, arguments);
+ },
+ // access
+ getRow: function(inRowIndex){
+ var row = this.data[inRowIndex];
+ if(!row){
+ this.preparePage(inRowIndex);
+ }
+ return row;
+ },
+ getDatum: function(inRowIndex, inColIndex){
+ var row = this.getRow(inRowIndex);
+ return (row ? row[inColIndex] : this.fields.get(inColIndex).na);
+ },
+ setDatum: function(inDatum, inRowIndex, inColIndex){
+ var row = this.getRow(inRowIndex);
+ if(row){
+ row[inColIndex] = inDatum;
+ this.datumChange(inDatum, inRowIndex, inColIndex);
+ }else{
+ console.debug('[' + this.declaredClass + '] dojox.grid.data.dynamic.set: cannot set data on an non-loaded row');
+ }
+ },
+ // sort
+ canSort: function(){
+ return false;
+ }
+});
+
+// FIXME: deprecated: (included for backward compatibility only)
+dojox.grid.data.table = dojox.grid.data.Table;
+dojox.grid.data.dynamic = dojox.grid.data.Dynamic;
+
+// we treat dojo.data stores as dynamic stores because no matter how they got
+// here, they should always fill that contract
+dojo.declare("dojox.grid.data.DojoData", dojox.grid.data.Dynamic, {
+ // summary:
+ // A grid data model for dynamic data retreived from a store which
+ // implements the dojo.data API set. Retrieves data automatically when
+ // requested and provides notification when data is received
+ // description:
+ // This store subclasses the Dynamic grid data object in order to
+ // provide paginated data access support, notification and view
+ // updates for stores which support those features, and simple
+ // field/column mapping for all dojo.data stores.
+ constructor: function(inFields, inData, args){
+ this.count = 1;
+ this._rowIdentities = {};
+ this._currentlyProcessing = [];
+ if(args){
+ dojo.mixin(this, args);
+ }
+ if(this.store){
+ var f = this.store.getFeatures();
+ this._canNotify = f['dojo.data.api.Notification'];
+ this._canWrite = f['dojo.data.api.Write'];
+ this._canIdentify = f['dojo.data.api.Identity'];
+ if(this._canNotify){
+ dojo.connect(this.store, "onSet", this, "_storeDatumChange");
+ dojo.connect(this.store, "onDelete", this, "_storeDatumDelete");
+ dojo.connect(this.store, "onNew", this, "_storeDatumNew");
+ }
+ if(this._canWrite) {
+ dojo.connect(this.store, "revert", this, "refresh");
+ }
+ }
+ },
+ markupFactory: function(args, node){
+ return new dojox.grid.data.DojoData(null, null, args);
+ },
+ query: { name: "*" }, // default, stupid query
+ store: null,
+ _currentlyProcessing: null,
+ _canNotify: false,
+ _canWrite: false,
+ _canIdentify: false,
+ _rowIdentities: {},
+ clientSort: false,
+ sortFields: null,
+ queryOptions: null,
+
+ // data
+ setData: function(inData){
+ this.store = inData;
+ this.data = [];
+ this.allChange();
+ },
+ setRowCount: function(inCount){
+ //console.debug("inCount:", inCount);
+ this.count = inCount;
+ this.allChange();
+ },
+ beginReturn: function(inCount){
+ if(this.count != inCount){
+ // this.setRowCount(0);
+ // this.clear();
+ // console.debug(this.count, inCount);
+ this.setRowCount(inCount);
+ }
+ },
+ _setupFields: function(dataItem){
+ // abort if we already have setup fields
+ if(this.fields._nameMaps){
+ return;
+ }
+ // set up field/index mappings
+ var m = {};
+ //console.debug("setting up fields", m);
+ var fields = dojo.map(this.store.getAttributes(dataItem),
+ function(item, idx){
+ m[item] = idx;
+ m[idx+".idx"] = item;
+ // name == display name, key = property name
+ return { name: item, key: item };
+ },
+ this
+ );
+ this.fields._nameMaps = m;
+ // console.debug("new fields:", fields);
+ this.fields.set(fields);
+ this.notify("FieldsChange");
+ },
+ _getRowFromItem: function(item){
+ // gets us the row object (and row index) of an item
+ },
+ _createRow: function(item){
+ var row = {};
+ row.__dojo_data_item = item;
+ dojo.forEach(this.fields.values, function(a){
+ value = this.store.getValue(item, a.name);
+ row[a.name] = (value === undefined || value === null)?"":value;
+ }, this);
+ return row;
+ },
+ processRows: function(items, request){
+ // console.debug(arguments);
+ if(!items || items.length == 0){ return; }
+ this._setupFields(items[0]);
+ dojo.forEach(items, function(item, idx){
+ var row = this._createRow(item);
+ this._setRowId(item, request.start, idx);
+ this.setRow(row, request.start+idx);
+ }, this);
+ // FIXME:
+ // Q: scott, steve, how the hell do we actually get this to update
+ // the visible UI for these rows?
+ // A: the goal is that Grid automatically updates to reflect changes
+ // in model. In this case, setRow -> rowChanged -> (observed by) Grid -> modelRowChange -> updateRow
+ },
+ // request data
+ requestRows: function(inRowIndex, inCount){
+ var row = inRowIndex || 0;
+ var params = {
+ start: row,
+ count: this.rowsPerPage,
+ query: this.query,
+ sort: this.sortFields,
+ queryOptions: this.queryOptions,
+ onBegin: dojo.hitch(this, "beginReturn"),
+ onComplete: dojo.hitch(this, "processRows"), // add to deferred?
+ onError: dojo.hitch(this, "processError")
+ };
+ this.store.fetch(params);
+ },
+ getDatum: function(inRowIndex, inColIndex){
+ //console.debug("getDatum", inRowIndex, inColIndex);
+ var row = this.getRow(inRowIndex);
+ var field = this.fields.values[inColIndex];
+ return row && field ? row[field.name] : field ? field.na : '?';
+ //var idx = row && this.fields._nameMaps[inColIndex+".idx"];
+ //return (row ? row[idx] : this.fields.get(inColIndex).na);
+ },
+ setDatum: function(inDatum, inRowIndex, inColIndex){
+ var n = this.fields._nameMaps[inColIndex+".idx"];
+ // console.debug("setDatum:", "n:"+n, inDatum, inRowIndex, inColIndex);
+ if(n){
+ this.data[inRowIndex][n] = inDatum;
+ this.datumChange(inDatum, inRowIndex, inColIndex);
+ }
+ },
+ // modification, update and store eventing
+ copyRow: function(inRowIndex){
+ var row = {};
+ var backstop = {};
+ var src = this.getRow(inRowIndex);
+ for(var x in src){
+ if(src[x] != backstop[x]){
+ row[x] = src[x];
+ }
+ }
+ return row;
+ },
+ _attrCompare: function(cache, data){
+ dojo.forEach(this.fields.values, function(a){
+ if(cache[a.name] != data[a.name]){ return false; }
+ }, this);
+ return true;
+ },
+ endModifyRow: function(inRowIndex){
+ var cache = this.cache[inRowIndex];
+ if(cache){
+ var data = this.getRow(inRowIndex);
+ if(!this._attrCompare(cache, data)){
+ this.update(cache, data, inRowIndex);
+ }
+ delete this.cache[inRowIndex];
+ }
+ },
+ cancelModifyRow: function(inRowIndex){
+ // console.debug("cancelModifyRow", arguments);
+ var cache = this.cache[inRowIndex];
+ if(cache){
+ this.setRow(cache, inRowIndex);
+ delete this.cache[inRowIndex];
+ }
+ },
+ _setRowId: function(item, offset, idx){
+ // FIXME: where else do we need to keep this in sync?
+ //Handle stores that implement identity and try to handle those that do not.
+ if (this._canIdentify) {
+ this._rowIdentities[this.store.getIdentity(item)] = {rowId: offset+idx, item: item};
+ }else{
+ var identity = dojo.toJson(this.query) + ":start:" + offset + ":idx:" + idx + ":sort:" + dojo.toJson(this.sortFields);
+ this._rowIdentities[identity] = {rowId: offset+idx, item: item};
+ }
+ },
+ _getRowId: function(item, isNotItem){
+ // summary:
+ // Function determine the row index for a particular item
+ // item:
+ // The store item to examine to determine row index.
+ // isNotItem:
+ // Boolean flag to indicate if the item passed is a store item or not.
+ var rowId = null;
+ //Handle identity and nonidentity capable stores.
+ if(this._canIdentify && !isNotItem){
+ rowId = this._rowIdentities[this.store.getIdentity(item)].rowId;
+ }else{
+ //Not efficient, but without identity support,
+ //not a better way to do it. Basically, do our best to locate it
+ //This may or may not work, but best we can do here.
+ var id;
+ for(id in this._rowIdentities){
+ if(this._rowIdentities[id].item === item){
+ rowId = this._rowIdentities[id].rowId;
+ break;
+ }
+ }
+ }
+ return rowId;
+ },
+ _storeDatumChange: function(item, attr, oldVal, newVal){
+ // the store has changed some data under us, need to update the display
+ var rowId = this._getRowId(item);
+ var row = this.getRow(rowId);
+ if(row){
+ row[attr] = newVal;
+ var colId = this.fields._nameMaps[attr];
+ this.notify("DatumChange", [ newVal, rowId, colId ]);
+ }
+ },
+ _storeDatumDelete: function(item){
+ if(dojo.indexOf(this._currentlyProcessing, item) != -1)
+ return;
+ // the store has deleted some item under us, need to remove that item from
+ // the view if possible. It may be the deleted item isn't even in the grid.
+ var rowId = this._getRowId(item, true);
+ if(rowId != null){
+ this._removeItems([rowId]);
+ }
+ },
+ _storeDatumNew: function(item){
+ if(this._disableNew){
+ return;
+ }
+ // the store has added some item under us, need to add it to the view.
+ this._insertItem(item, this.data.length);
+ },
+ insert: function(item, index){
+ // Push the given item back to the store
+ this._disableNew = true;
+ var i = this.store.newItem(item);
+ this._disableNew = false;
+ this._insertItem(i, index);
+ },
+ _insertItem: function(storeItem, index){
+ // Set up our fields if we haven't already
+ if(!this.fields._nameMaps){
+ this._setupFields(storeItem);
+ }
+ var row = this._createRow(storeItem);
+ for(var i in this._rowIdentities){ //increment all the remaining row ids up one
+ var rowIdentity = this._rowIdentities[i];
+ if(rowIdentity.rowId >= index){
+ rowIdentity.rowId++;
+ }
+ }
+ this._setRowId(storeItem, 0, index);
+ dojox.grid.data.Dynamic.prototype.insert.apply(this, [row, index]);
+ },
+ datumChange: function(value, rowIdx, colIdx){
+ if(this._canWrite){
+ // we're chaning some data, which means we need to write back
+ var row = this.getRow(rowIdx);
+ var field = this.fields._nameMaps[colIdx+".idx"];
+ this.store.setValue(row.__dojo_data_item, field, value);
+ // we don't need to call DatumChange, an eventing store will tell
+ // us about the row change events
+ }else{
+ // we can't write back, so just go ahead and change our local copy
+ // of the data
+ this.notify("DatumChange", arguments);
+ }
+ },
+ insertion: function(/* index */){
+ console.debug("Insertion", arguments);
+ this.notify("Insertion", arguments);
+ this.notify("Change", arguments);
+ },
+ removal: function(/* keys */){
+ console.debug("Removal", arguments);
+ this.notify("Removal", arguments);
+ this.notify("Change", arguments);
+ },
+ remove: function(inRowIndexes){
+ // summary:
+ // Function to remove a set of items from the store based on the row index.
+ // inRowIndexes:
+ // An array of row indexes from the grid to remove from the store.
+ /* Call delete on the store */
+ for(var i=inRowIndexes.length-1; i>=0; i--){
+ // Need to find the item, then remove each from the data store
+ var item = this.data[inRowIndexes[i]].__dojo_data_item;
+ this._currentlyProcessing.push(item);
+ this.store.deleteItem(item);
+ }
+ /* Remove from internal data structure and the view */
+ this._removeItems(inRowIndexes);
+ this._currentlyProcessing = [];
+ },
+ _removeItems: function(inRowIndexes /*array*/){
+ // summary:
+ // Function to remove a set of items from the store based on the row index.
+ // inRowIndexes:
+ // An array of row indexes from the grid to remove from the store.
+ dojox.grid.data.Dynamic.prototype.remove.apply(this, arguments);
+ // Rebuild _rowIdentities
+ this._rowIdentities = {};
+ for (var i = 0; i < this.data.length; i++){
+ this._setRowId(this.data[i].__dojo_data_item, 0, i);
+ }
+ },
+ canSort: function(){
+ // Q: Return true and re-issue the queries?
+ // A: Return true only. Re-issue the query in 'sort'.
+ // Note, above are original comments :)
+ return true;
+ },
+ sort: function(colIndex){
+ var col = Math.abs(colIndex) - 1;
+ this.sortFields = [{'attribute': this.fields.values[col].name, 'descending': (colIndex>0)}];
+
+ // Since we're relying on the data store to sort, we have to refresh our data.
+ this.refresh();
+ },
+ refresh: function(){
+ // summary:
+ // Function to cause the model to re-query the store and rebuild the current viewport.
+ this.clearData(true);
+ this.requestRows();
+ },
+ clearData: function(/* boolean */ keepStore){
+ this._rowIdentities = {};
+ this.pages = [];
+ this.bop = this.eop = -1;
+ this.count = 0;
+ this.setData((keepStore?this.store:[]));
+ },
+ processError: function(error, request){
+ // summary:
+ // Hook function to trap error messages from the store and emit them.
+ // Intended for connecting to and handling the error object or at least reporting it.
+ //
+ // error:
+ // The error object returned by the store when a problem occurred.
+ // request:
+ // The request object that caused the error.
+ console.log(error);
+ }
+});
+
+}
diff --git a/includes/js/dojox/grid/_grid/Grid.css b/includes/js/dojox/grid/_grid/Grid.css
new file mode 100644
index 0000000..655be54
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/Grid.css
@@ -0,0 +1,201 @@
+.dojoxGrid {
+ position: relative;
+ background-color: #EBEADB;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ -moz-outline-style: none;
+ outline: none;
+ overflow: hidden;
+ height: 0;
+}
+.dojoxGrid table {
+ padding: 0;
+}
+.dojoxGrid td {
+ -moz-outline: none;
+}
+.dojoxGrid-master-header {
+ position: relative;
+}
+.dojoxGrid-master-view {
+ position: relative;
+}
+.dojoxGrid-view {
+ position: absolute;
+ overflow: hidden;
+}
+.dojoxGrid-header {
+ position: absolute;
+ overflow: hidden;
+}
+.dojoxGrid-header {
+ background-color: #E8E1CF;
+}
+.dojoxGrid-header table {
+ text-align: center;
+}
+.dojoxGrid-header .dojoxGrid-cell-content {
+ text-align: center;
+}
+.dojoxGrid-header .dojoxGrid-cell {
+ border: 1px solid;
+ border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
+ background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
+ padding-bottom: 2px;
+}
+.dojoxGrid-header .dojoxGrid-cell-over {
+ background-image: none;
+ background-color: white;
+ border-bottom-color: #FEBE47;
+ margin-bottom: 0;
+ padding-bottom: 0;
+ border-bottom-width: 3px;
+}
+.dojoxGrid-sort-down {
+ background: url(images/grid_sort_down.gif) left no-repeat;
+ padding-left:16px;
+ margin-left:4px;
+}
+.dojoxGrid-sort-up {
+ background: url(images/grid_sort_up.gif) left no-repeat;
+ padding-left:16px;
+ margin-left:4px;
+}
+.dojoxGrid-scrollbox {
+ position: relative;
+ overflow: scroll;
+ background-color: white;
+ width: 100%;
+}
+.dojoxGrid-content {
+ position: relative;
+ overflow: hidden;
+ -moz-outline-style: none;
+ outline: none;
+}
+.dojoxGrid-rowbar {
+ border: 1px solid;
+ border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
+ border-top: none;
+ background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
+}
+.dojoxGrid-rowbar-inner {
+ border-top: 1px solid #F6F4EB;
+}
+.dojoxGrid-rowbar-over {
+ background-image: none;
+ background-color: white;
+ border-top-color: #FEBE47;
+ border-bottom-color: #FEBE47;
+}
+.dojoxGrid-rowbar-selected {
+ background-color: #D9E8F9;
+ background-image: none;
+
+ background-position: center;
+ background-repeat: no-repeat;
+}
+.dojoxGrid-row {
+ position: relative;
+ width: 9000em;
+}
+.dojoxGrid-row {
+
+ border: 1px solid #E8E4D8;
+ border-color: #F8F7F1;
+
+ border-left: none;
+ border-right: none;
+ background-color: white;
+ border-top: none;
+}
+.dojoxGrid-row-over {
+ border-top-color: #FEBE47;
+ border-bottom-color: #FEBE47;
+
+
+
+}
+.dojoxGrid-row-odd {
+ background-color: #FFFDF3;
+
+}
+.dojoxGrid-row-selected {
+ background-color: #D9E8F9;
+}
+.dojoxGrid-row-table {
+ table-layout: fixed;
+ width: 0;
+}
+.dojoxGrid-invisible {
+ visibility: hidden;
+}
+.Xdojo-ie .dojoxGrid-invisible {
+ display: none;
+}
+.dojoxGrid-invisible td, .dojoxGrid-header .dojoxGrid-invisible td {
+ border-top-width: 0;
+ border-bottom-width: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ height: 0;
+ overflow: hidden;
+}
+.dojoxGrid-cell {
+ border: 1px solid;
+ border-color: #EBEADB;
+ border-right-color: #D5CDB5;
+ padding: 3px 3px 3px 3px;
+ text-align: left;
+ overflow: hidden;
+}
+.dojoxGrid-cell-focus {
+ border: 1px dashed blue;
+}
+.dojoxGrid-cell-over {
+ border: 1px dotted #FEBE47;
+}
+.dojoxGrid-cell-focus.dojoxGrid-cell-over {
+ border: 1px dotted green;
+}
+.dojoxGrid-cell-clip {
+ width: 100%;
+ overflow: hidden;
+ white-space:nowrap;
+ text-overflow: ellipsis;
+}
+.dojoxGrid-row-editing td {
+ background-color: #F4FFF4;
+}
+.dojoxGrid-row-inserting td {
+ background-color: #F4FFF4;
+}
+.dojoxGrid-row-inflight td {
+ background-color: #F2F7B7;
+}
+.dojoxGrid-row-error td {
+ background-color: #F8B8B6;
+}
+.dojoxGrid-input, .dojoxGrid-select, .dojoxGrid-textarea {
+ margin: 0;
+ padding: 0;
+ border-style: none;
+ width: 100%;
+ font-size: 100%;
+ font-family: inherit;
+}
+.dojoxGrid-hidden-focus {
+ position: absolute;
+ left: -1000px;
+ top: -1000px;
+ height: 0px, width: 0px;
+}
+.gridArrowButtonChar {
+ display:none !important;
+}
+.dijit_a11y .gridArrowButtonChar {
+ display:inline !important;
+}
+.dijit_a11y .dojoxGrid-sort-down, .dijit_a11y .dojoxGrid-sort-up {
+ margin-left: 0;
+ padding-left: 0;
+}
diff --git a/includes/js/dojox/grid/_grid/Grid.css.commented.css b/includes/js/dojox/grid/_grid/Grid.css.commented.css
new file mode 100644
index 0000000..227ffa3
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/Grid.css.commented.css
@@ -0,0 +1,258 @@
+.dojoxGrid {
+ position: relative;
+ background-color: #EBEADB;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ -moz-outline-style: none;
+ outline: none;
+ overflow: hidden;
+ height: 0;
+}
+
+.dojoxGrid table {
+ padding: 0;
+}
+
+.dojoxGrid td {
+ -moz-outline: none;
+}
+
+/* master header */
+
+.dojoxGrid-master-header {
+ position: relative;
+}
+
+/* master view */
+
+.dojoxGrid-master-view {
+ position: relative;
+}
+
+/* views */
+
+.dojoxGrid-view {
+ position: absolute;
+ overflow: hidden;
+}
+
+/* header */
+
+.dojoxGrid-header {
+ position: absolute;
+ overflow: hidden;
+}
+
+.dojoxGrid-header {
+ background-color: #E8E1CF;
+}
+
+.dojoxGrid-header table {
+ text-align: center;
+}
+
+.dojoxGrid-header .dojoxGrid-cell-content {
+ text-align: center;
+}
+
+.dojoxGrid-header .dojoxGrid-cell {
+ border: 1px solid;
+ border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
+ background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
+ padding-bottom: 2px;
+}
+
+.dojoxGrid-header .dojoxGrid-cell-over {
+ background-image: none;
+ background-color: white;
+ border-bottom-color: #FEBE47;
+ margin-bottom: 0;
+ padding-bottom: 0;
+ border-bottom-width: 3px;
+}
+
+.dojoxGrid-sort-down {
+ background: url(images/grid_sort_down.gif) left no-repeat;
+ padding-left:16px;
+ margin-left:4px;
+}
+
+.dojoxGrid-sort-up {
+ background: url(images/grid_sort_up.gif) left no-repeat;
+ padding-left:16px;
+ margin-left:4px;
+}
+
+/* content */
+
+.dojoxGrid-scrollbox {
+ position: relative;
+ overflow: scroll;
+ background-color: white;
+ width: 100%;
+}
+
+.dojoxGrid-content {
+ position: relative;
+ overflow: hidden;
+ -moz-outline-style: none;
+ outline: none;
+}
+
+/* rowbar */
+
+.dojoxGrid-rowbar {
+ border: 1px solid;
+ border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
+ border-top: none;
+ background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
+}
+
+.dojoxGrid-rowbar-inner {
+ border-top: 1px solid #F6F4EB;
+}
+
+.dojoxGrid-rowbar-over {
+ background-image: none;
+ background-color: white;
+ border-top-color: #FEBE47;
+ border-bottom-color: #FEBE47;
+}
+
+.dojoxGrid-rowbar-selected {
+ background-color: #D9E8F9;
+ background-image: none;
+ /*background-image: url(images/grid_green_dot.gif);*/
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+/* rows */
+
+.dojoxGrid-row {
+ position: relative;
+ width: 9000em;
+}
+
+.dojoxGrid-row {
+ /*border: 1px solid #E8E4D8;*/
+ border: 1px solid #E8E4D8;
+ border-color: #F8F7F1;
+ /*padding: 0 0 1px 0;*/
+ border-left: none;
+ border-right: none;
+ background-color: white;
+ border-top: none;
+}
+
+.dojoxGrid-row-over {
+ border-top-color: #FEBE47;
+ border-bottom-color: #FEBE47;
+ /*border-bottom-width: 2px;
+ padding-bottom: 0;*/
+ /*background-color: #FFDD9D;*/
+ /*background-color: #FDFDFD;*/
+}
+
+.dojoxGrid-row-odd {
+ background-color: #FFFDF3;
+ /*background-color: #F9F7E8;*/
+}
+
+.dojoxGrid-row-selected {
+ background-color: #D9E8F9;
+}
+
+.dojoxGrid-row-table {
+ table-layout: fixed;
+ width: 0;
+}
+
+.dojoxGrid-invisible {
+ visibility: hidden;
+}
+
+.Xdojo-ie .dojoxGrid-invisible {
+ display: none;
+}
+
+.dojoxGrid-invisible td, .dojoxGrid-header .dojoxGrid-invisible td {
+ border-top-width: 0;
+ border-bottom-width: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ height: 0;
+ overflow: hidden;
+}
+
+/* cells */
+
+.dojoxGrid-cell {
+ border: 1px solid;
+ border-color: #EBEADB;
+ border-right-color: #D5CDB5;
+ padding: 3px 3px 3px 3px;
+ text-align: left;
+ overflow: hidden;
+}
+
+.dojoxGrid-cell-focus {
+ border: 1px dashed blue;
+}
+
+.dojoxGrid-cell-over {
+ border: 1px dotted #FEBE47;
+}
+
+.dojoxGrid-cell-focus.dojoxGrid-cell-over {
+ border: 1px dotted green;
+}
+
+.dojoxGrid-cell-clip {
+ width: 100%;
+ overflow: hidden;
+ white-space:nowrap;
+ text-overflow: ellipsis;
+}
+
+/* editing */
+
+.dojoxGrid-row-editing td {
+ background-color: #F4FFF4;
+}
+
+.dojoxGrid-row-inserting td {
+ background-color: #F4FFF4;
+}
+.dojoxGrid-row-inflight td {
+ background-color: #F2F7B7;
+}
+.dojoxGrid-row-error td {
+ background-color: #F8B8B6;
+}
+
+.dojoxGrid-input, .dojoxGrid-select, .dojoxGrid-textarea {
+ margin: 0;
+ padding: 0;
+ border-style: none;
+ width: 100%;
+ font-size: 100%;
+ font-family: inherit;
+}
+
+.dojoxGrid-hidden-focus {
+ position: absolute;
+ left: -1000px;
+ top: -1000px;
+ height: 0px, width: 0px;
+}
+
+.gridArrowButtonChar {
+ display:none !important;
+}
+.dijit_a11y .gridArrowButtonChar {
+ display:inline !important;
+}
+.dijit_a11y .dojoxGrid-sort-down, .dijit_a11y .dojoxGrid-sort-up {
+ margin-left: 0;
+ padding-left: 0;
+}
diff --git a/includes/js/dojox/grid/_grid/Grid_rtl.css b/includes/js/dojox/grid/_grid/Grid_rtl.css
new file mode 100644
index 0000000..88ab215
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/Grid_rtl.css
@@ -0,0 +1,8 @@
+.dijitRtl .dojoxGrid-header table {
+}
+.dj_ie .dijitRtl .dojoxGrid-header table {
+ float:none;
+}
+.dijitRtl .dojoxGrid-content {
+ float:left;
+}
diff --git a/includes/js/dojox/grid/_grid/Grid_rtl.css.commented.css b/includes/js/dojox/grid/_grid/Grid_rtl.css.commented.css
new file mode 100644
index 0000000..c240b4c
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/Grid_rtl.css.commented.css
@@ -0,0 +1,10 @@
+.dijitRtl .dojoxGrid-header table {
+}
+
+.dj_ie .dijitRtl .dojoxGrid-header table {
+ float:none;
+}
+
+.dijitRtl .dojoxGrid-content {
+ float:left;
+}
diff --git a/includes/js/dojox/grid/_grid/builder.js b/includes/js/dojox/grid/_grid/builder.js
new file mode 100644
index 0000000..dccf7e2
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/builder.js
@@ -0,0 +1,522 @@
+if(!dojo._hasResource["dojox.grid._grid.builder"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._grid.builder"] = true;
+dojo.provide("dojox.grid._grid.builder");
+dojo.require("dojox.grid._grid.drag");
+
+dojo.declare("dojox.grid.Builder",
+ null,
+ {
+ // summary:
+ // Base class to produce html for grid content.
+ // Also provide event decoration, providing grid related information inside the event object
+ // passed to grid events.
+ constructor: function(inView){
+ this.view = inView;
+ this.grid = inView.grid;
+ },
+
+ view: null,
+ // boilerplate HTML
+ _table: '<table class="dojoxGrid-row-table" border="0" cellspacing="0" cellpadding="0" role="wairole:presentation">',
+
+ // generate starting tags for a cell
+ generateCellMarkup: function(inCell, inMoreStyles, inMoreClasses, isHeader){
+ var result = [], html;
+ if (isHeader){
+ html = [ '<th tabIndex="-1" role="wairole:columnheader"' ];
+ }else{
+ html = [ '<td tabIndex="-1" role="wairole:gridcell"' ];
+ }
+ inCell.colSpan && html.push(' colspan="', inCell.colSpan, '"');
+ inCell.rowSpan && html.push(' rowspan="', inCell.rowSpan, '"');
+ html.push(' class="dojoxGrid-cell ');
+ inCell.classes && html.push(inCell.classes, ' ');
+ inMoreClasses && html.push(inMoreClasses, ' ');
+ // result[0] => td opener, style
+ result.push(html.join(''));
+ // SLOT: result[1] => td classes
+ result.push('');
+ html = ['" idx="', inCell.index, '" style="'];
+ html.push(inCell.styles, inMoreStyles||'');
+ inCell.unitWidth && html.push('width:', inCell.unitWidth, ';');
+ // result[2] => markup
+ result.push(html.join(''));
+ // SLOT: result[3] => td style
+ result.push('');
+ html = [ '"' ];
+ inCell.attrs && html.push(" ", inCell.attrs);
+ html.push('>');
+ // result[4] => td postfix
+ result.push(html.join(''));
+ // SLOT: result[5] => content
+ result.push('');
+ // result[6] => td closes
+ result.push('</td>');
+ return result; // Array
+ },
+
+ // cell finding
+ isCellNode: function(inNode){
+ return Boolean(inNode && inNode.getAttribute && inNode.getAttribute("idx"));
+ },
+
+ getCellNodeIndex: function(inCellNode){
+ return inCellNode ? Number(inCellNode.getAttribute("idx")) : -1;
+ },
+
+ getCellNode: function(inRowNode, inCellIndex){
+ for(var i=0, row; row=dojox.grid.getTr(inRowNode.firstChild, i); i++){
+ for(var j=0, cell; cell=row.cells[j]; j++){
+ if(this.getCellNodeIndex(cell) == inCellIndex){
+ return cell;
+ }
+ }
+ }
+ },
+
+ findCellTarget: function(inSourceNode, inTopNode){
+ var n = inSourceNode;
+ while(n && (!this.isCellNode(n) || (dojox.grid.gridViewTag in n.offsetParent.parentNode && n.offsetParent.parentNode[dojox.grid.gridViewTag] != this.view.id)) && (n!=inTopNode)){
+ n = n.parentNode;
+ }
+ return n!=inTopNode ? n : null
+ },
+
+ // event decoration
+ baseDecorateEvent: function(e){
+ e.dispatch = 'do' + e.type;
+ e.grid = this.grid;
+ e.sourceView = this.view;
+ e.cellNode = this.findCellTarget(e.target, e.rowNode);
+ e.cellIndex = this.getCellNodeIndex(e.cellNode);
+ e.cell = (e.cellIndex >= 0 ? this.grid.getCell(e.cellIndex) : null);
+ },
+
+ // event dispatch
+ findTarget: function(inSource, inTag){
+ var n = inSource;
+ while(n && (n!=this.domNode) && (!(inTag in n) || (dojox.grid.gridViewTag in n && n[dojox.grid.gridViewTag] != this.view.id))){
+ n = n.parentNode;
+ }
+ return (n != this.domNode) ? n : null;
+ },
+
+ findRowTarget: function(inSource){
+ return this.findTarget(inSource, dojox.grid.rowIndexTag);
+ },
+
+ isIntraNodeEvent: function(e){
+ try{
+ return (e.cellNode && e.relatedTarget && dojo.isDescendant(e.relatedTarget, e.cellNode));
+ }catch(x){
+ // e.relatedTarget has permission problem in FF if it's an input: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
+ return false;
+ }
+ },
+
+ isIntraRowEvent: function(e){
+ try{
+ var row = e.relatedTarget && this.findRowTarget(e.relatedTarget);
+ return !row && (e.rowIndex==-1) || row && (e.rowIndex==row.gridRowIndex);
+ }catch(x){
+ // e.relatedTarget on INPUT has permission problem in FF: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
+ return false;
+ }
+ },
+
+ dispatchEvent: function(e){
+ if(e.dispatch in this){
+ return this[e.dispatch](e);
+ }
+ },
+
+ // dispatched event handlers
+ domouseover: function(e){
+ if(e.cellNode && (e.cellNode!=this.lastOverCellNode)){
+ this.lastOverCellNode = e.cellNode;
+ this.grid.onMouseOver(e);
+ }
+ this.grid.onMouseOverRow(e);
+ },
+
+ domouseout: function(e){
+ if(e.cellNode && (e.cellNode==this.lastOverCellNode) && !this.isIntraNodeEvent(e, this.lastOverCellNode)){
+ this.lastOverCellNode = null;
+ this.grid.onMouseOut(e);
+ if(!this.isIntraRowEvent(e)){
+ this.grid.onMouseOutRow(e);
+ }
+ }
+ },
+
+ domousedown: function(e){
+ if (e.cellNode)
+ this.grid.onMouseDown(e);
+ this.grid.onMouseDownRow(e)
+ }
+
+});
+
+dojo.declare("dojox.grid.contentBuilder",
+ dojox.grid.Builder,
+ {
+ // summary:
+ // Produces html for grid data content. Owned by grid and used internally
+ // for rendering data. Override to implement custom rendering.
+ update: function(){
+ this.prepareHtml();
+ },
+
+ // cache html for rendering data rows
+ prepareHtml: function(){
+ var defaultGet=this.grid.get, rows=this.view.structure.rows;
+ for(var j=0, row; (row=rows[j]); j++){
+ for(var i=0, cell; (cell=row[i]); i++){
+ cell.get = cell.get || (cell.value == undefined) && defaultGet;
+ cell.markup = this.generateCellMarkup(cell, cell.cellStyles, cell.cellClasses, false);
+ }
+ }
+ },
+
+ // time critical: generate html using cache and data source
+ generateHtml: function(inDataIndex, inRowIndex){
+ var
+ html = [ this._table ],
+ v = this.view,
+ obr = v.onBeforeRow,
+ rows = v.structure.rows;
+
+ obr && obr(inRowIndex, rows);
+ for(var j=0, row; (row=rows[j]); j++){
+ if(row.hidden || row.header){
+ continue;
+ }
+ html.push(!row.invisible ? '<tr>' : '<tr class="dojoxGrid-invisible">');
+ for(var i=0, cell, m, cc, cs; (cell=row[i]); i++){
+ m = cell.markup, cc = cell.customClasses = [], cs = cell.customStyles = [];
+ // content (format can fill in cc and cs as side-effects)
+ m[5] = cell.format(inDataIndex);
+ // classes
+ m[1] = cc.join(' ');
+ // styles
+ m[3] = cs.join(';');
+ // in-place concat
+ html.push.apply(html, m);
+ }
+ html.push('</tr>');
+ }
+ html.push('</table>');
+ return html.join(''); // String
+ },
+
+ decorateEvent: function(e){
+ e.rowNode = this.findRowTarget(e.target);
+ if(!e.rowNode){return false};
+ e.rowIndex = e.rowNode[dojox.grid.rowIndexTag];
+ this.baseDecorateEvent(e);
+ e.cell = this.grid.getCell(e.cellIndex);
+ return true; // Boolean
+ }
+
+});
+
+dojo.declare("dojox.grid.headerBuilder",
+ dojox.grid.Builder,
+ {
+ // summary:
+ // Produces html for grid header content. Owned by grid and used internally
+ // for rendering data. Override to implement custom rendering.
+
+ bogusClickTime: 0,
+ overResizeWidth: 4,
+ minColWidth: 1,
+
+ // FIXME: isn't this getting mixed from dojox.grid.Builder, -1 character?
+ _table: '<table class="dojoxGrid-row-table" border="0" cellspacing="0" cellpadding="0" role="wairole:presentation"',
+
+ update: function(){
+ this.tableMap = new dojox.grid.tableMap(this.view.structure.rows);
+ },
+
+ generateHtml: function(inGetValue, inValue){
+ var html = [this._table], rows = this.view.structure.rows;
+
+ // render header with appropriate width, if possible so that views with flex columns are correct height
+ if(this.view.viewWidth){
+ html.push([' style="width:', this.view.viewWidth, ';"'].join(''));
+ }
+ html.push('>');
+ dojox.grid.fire(this.view, "onBeforeRow", [-1, rows]);
+ for(var j=0, row; (row=rows[j]); j++){
+ if(row.hidden){
+ continue;
+ }
+ html.push(!row.invisible ? '<tr>' : '<tr class="dojoxGrid-invisible">');
+ for(var i=0, cell, markup; (cell=row[i]); i++){
+ cell.customClasses = [];
+ cell.customStyles = [];
+ markup = this.generateCellMarkup(cell, cell.headerStyles, cell.headerClasses, true);
+ // content
+ markup[5] = (inValue != undefined ? inValue : inGetValue(cell));
+ // styles
+ markup[3] = cell.customStyles.join(';');
+ // classes
+ markup[1] = cell.customClasses.join(' '); //(cell.customClasses ? ' ' + cell.customClasses : '');
+ html.push(markup.join(''));
+ }
+ html.push('</tr>');
+ }
+ html.push('</table>');
+ return html.join('');
+ },
+
+ // event helpers
+ getCellX: function(e){
+ var x = e.layerX;
+ if(dojo.isMoz){
+ var n = dojox.grid.ascendDom(e.target, dojox.grid.makeNotTagName("th"));
+ x -= (n && n.offsetLeft) || 0;
+ var t = e.sourceView.getScrollbarWidth();
+ if(!dojo._isBodyLtr() && e.sourceView.headerNode.scrollLeft < t)
+ x -= t;
+ //x -= getProp(ascendDom(e.target, mkNotTagName("td")), "offsetLeft") || 0;
+ }
+ var n = dojox.grid.ascendDom(e.target, function(){
+ if(!n || n == e.cellNode){
+ return false;
+ }
+ // Mozilla 1.8 (FF 1.5) has a bug that makes offsetLeft = -parent border width
+ // when parent has border, overflow: hidden, and is positioned
+ // handle this problem here ... not a general solution!
+ x += (n.offsetLeft < 0 ? 0 : n.offsetLeft);
+ return true;
+ });
+ return x;
+ },
+
+ // event decoration
+ decorateEvent: function(e){
+ this.baseDecorateEvent(e);
+ e.rowIndex = -1;
+ e.cellX = this.getCellX(e);
+ return true;
+ },
+
+ // event handlers
+ // resizing
+ prepareResize: function(e, mod){
+ var i = dojox.grid.getTdIndex(e.cellNode);
+ e.cellNode = (i ? e.cellNode.parentNode.cells[i+mod] : null);
+ e.cellIndex = (e.cellNode ? this.getCellNodeIndex(e.cellNode) : -1);
+ return Boolean(e.cellNode);
+ },
+
+ canResize: function(e){
+ if(!e.cellNode || e.cellNode.colSpan > 1){
+ return false;
+ }
+ var cell = this.grid.getCell(e.cellIndex);
+ return !cell.noresize && !cell.isFlex();
+ },
+
+ overLeftResizeArea: function(e){
+ if(dojo._isBodyLtr()){
+ return (e.cellIndex>0) && (e.cellX < this.overResizeWidth) && this.prepareResize(e, -1);
+ }
+ return t = e.cellNode && (e.cellX < this.overResizeWidth);
+ },
+
+ overRightResizeArea: function(e){
+ if(dojo._isBodyLtr()){
+ return e.cellNode && (e.cellX >= e.cellNode.offsetWidth - this.overResizeWidth);
+ }
+ return (e.cellIndex>0) && (e.cellX >= e.cellNode.offsetWidth - this.overResizeWidth) && this.prepareResize(e, -1);
+ },
+
+ domousemove: function(e){
+ //console.log(e.cellIndex, e.cellX, e.cellNode.offsetWidth);
+ var c = (this.overRightResizeArea(e) ? 'e-resize' : (this.overLeftResizeArea(e) ? 'w-resize' : ''));
+ if(c && !this.canResize(e)){
+ c = 'not-allowed';
+ }
+ e.sourceView.headerNode.style.cursor = c || ''; //'default';
+ if (c)
+ dojo.stopEvent(e);
+ },
+
+ domousedown: function(e){
+ if(!dojox.grid.drag.dragging){
+ if((this.overRightResizeArea(e) || this.overLeftResizeArea(e)) && this.canResize(e)){
+ this.beginColumnResize(e);
+ }else{
+ this.grid.onMouseDown(e);
+ this.grid.onMouseOverRow(e);
+ }
+ //else{
+ // this.beginMoveColumn(e);
+ //}
+ }
+ },
+
+ doclick: function(e) {
+ if (new Date().getTime() < this.bogusClickTime) {
+ dojo.stopEvent(e);
+ return true;
+ }
+ },
+
+ // column resizing
+ beginColumnResize: function(e){
+ dojo.stopEvent(e);
+ var spanners = [], nodes = this.tableMap.findOverlappingNodes(e.cellNode);
+ for(var i=0, cell; (cell=nodes[i]); i++){
+ spanners.push({ node: cell, index: this.getCellNodeIndex(cell), width: cell.offsetWidth });
+ //console.log("spanner: " + this.getCellNodeIndex(cell));
+ }
+ var drag = {
+ scrollLeft: e.sourceView.headerNode.scrollLeft,
+ view: e.sourceView,
+ node: e.cellNode,
+ index: e.cellIndex,
+ w: e.cellNode.clientWidth,
+ spanners: spanners
+ };
+ //console.log(drag.index, drag.w);
+ dojox.grid.drag.start(e.cellNode, dojo.hitch(this, 'doResizeColumn', drag), dojo.hitch(this, 'endResizeColumn', drag), e);
+ },
+
+ doResizeColumn: function(inDrag, inEvent){
+ var isLtr = dojo._isBodyLtr();
+ if(isLtr){
+ var w = inDrag.w + inEvent.deltaX;
+ }else{
+ var w = inDrag.w - inEvent.deltaX;
+ }
+ if(w >= this.minColWidth){
+ for(var i=0, s, sw; (s=inDrag.spanners[i]); i++){
+ if(isLtr){
+ sw = s.width + inEvent.deltaX;
+ }else{
+ sw = s.width - inEvent.deltaX;
+ }
+ s.node.style.width = sw + 'px';
+ inDrag.view.setColWidth(s.index, sw);
+ //console.log('setColWidth', '#' + s.index, sw + 'px');
+ }
+ inDrag.node.style.width = w + 'px';
+ inDrag.view.setColWidth(inDrag.index, w);
+ if(!isLtr){
+ inDrag.view.headerNode.scrollLeft = (inDrag.scrollLeft - inEvent.deltaX);
+ }
+ }
+ if(inDrag.view.flexCells && !inDrag.view.testFlexCells()){
+ var t = dojox.grid.findTable(inDrag.node);
+ t && (t.style.width = '');
+ }
+ },
+
+ endResizeColumn: function(inDrag){
+ this.bogusClickTime = new Date().getTime() + 30;
+ setTimeout(dojo.hitch(inDrag.view, "update"), 50);
+ }
+
+});
+
+dojo.declare("dojox.grid.tableMap",
+ null,
+ {
+ // summary:
+ // Maps an html table into a structure parsable for information about cell row and col spanning.
+ // Used by headerBuilder
+ constructor: function(inRows){
+ this.mapRows(inRows);
+ },
+
+ map: null,
+
+ mapRows: function(inRows){
+ // summary: Map table topography
+
+ //console.log('mapRows');
+ // # of rows
+ var rowCount = inRows.length;
+ if(!rowCount){
+ return;
+ }
+ // map which columns and rows fill which cells
+ this.map = [ ];
+ for(var j=0, row; (row=inRows[j]); j++){
+ this.map[j] = [];
+ }
+ for(var j=0, row; (row=inRows[j]); j++){
+ for(var i=0, x=0, cell, colSpan, rowSpan; (cell=row[i]); i++){
+ while (this.map[j][x]){x++};
+ this.map[j][x] = { c: i, r: j };
+ rowSpan = cell.rowSpan || 1;
+ colSpan = cell.colSpan || 1;
+ for(var y=0; y<rowSpan; y++){
+ for(var s=0; s<colSpan; s++){
+ this.map[j+y][x+s] = this.map[j][x];
+ }
+ }
+ x += colSpan;
+ }
+ }
+ //this.dumMap();
+ },
+
+ dumpMap: function(){
+ for(var j=0, row, h=''; (row=this.map[j]); j++,h=''){
+ for(var i=0, cell; (cell=row[i]); i++){
+ h += cell.r + ',' + cell.c + ' ';
+ }
+ console.log(h);
+ }
+ },
+
+ getMapCoords: function(inRow, inCol){
+ // summary: Find node's map coords by it's structure coords
+ for(var j=0, row; (row=this.map[j]); j++){
+ for(var i=0, cell; (cell=row[i]); i++){
+ if(cell.c==inCol && cell.r == inRow){
+ return { j: j, i: i };
+ }
+ //else{console.log(inRow, inCol, ' : ', i, j, " : ", cell.r, cell.c); };
+ }
+ }
+ return { j: -1, i: -1 };
+ },
+
+ getNode: function(inTable, inRow, inCol){
+ // summary: Find a node in inNode's table with the given structure coords
+ var row = inTable && inTable.rows[inRow];
+ return row && row.cells[inCol];
+ },
+
+ _findOverlappingNodes: function(inTable, inRow, inCol){
+ var nodes = [];
+ var m = this.getMapCoords(inRow, inCol);
+ //console.log("node j: %d, i: %d", m.j, m.i);
+ var row = this.map[m.j];
+ for(var j=0, row; (row=this.map[j]); j++){
+ if(j == m.j){ continue; }
+ with(row[m.i]){
+ //console.log("overlaps: r: %d, c: %d", r, c);
+ var n = this.getNode(inTable, r, c);
+ if(n){ nodes.push(n); }
+ }
+ }
+ //console.log(nodes);
+ return nodes;
+ },
+
+ findOverlappingNodes: function(inNode){
+ return this._findOverlappingNodes(dojox.grid.findTable(inNode), dojox.grid.getTrIndex(inNode.parentNode), dojox.grid.getTdIndex(inNode));
+ }
+
+});
+
+dojox.grid.rowIndexTag = "gridRowIndex";
+dojox.grid.gridViewTag = "gridView";
+
+}
diff --git a/includes/js/dojox/grid/_grid/cell.js b/includes/js/dojox/grid/_grid/cell.js
new file mode 100644
index 0000000..52f92e8
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/cell.js
@@ -0,0 +1,66 @@
+if(!dojo._hasResource["dojox.grid._grid.cell"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._grid.cell"] = true;
+dojo.provide("dojox.grid._grid.cell");
+
+dojo.declare("dojox.grid.cell", null, {
+ // summary:
+ // Respresents a grid cell and contains information about column options and methods
+ // for retrieving cell related information.
+ // Each column in a grid layout has a cell object and most events and many methods
+ // provide access to these objects.
+ styles: '',
+ constructor: function(inProps){
+ dojo.mixin(this, inProps);
+ if(this.editor){this.editor = new this.editor(this);}
+ },
+ // data source
+ format: function(inRowIndex){
+ // summary:
+ // provides the html for a given grid cell.
+ // inRowIndex: int
+ // grid row index
+ // returns: html for a given grid cell
+ var f, i=this.grid.edit.info, d=this.get ? this.get(inRowIndex) : this.value;
+ if(this.editor && (this.editor.alwaysOn || (i.rowIndex==inRowIndex && i.cell==this))){
+ return this.editor.format(d, inRowIndex);
+ }else{
+ return (f = this.formatter) ? f.call(this, d, inRowIndex) : d;
+ }
+ },
+ // utility
+ getNode: function(inRowIndex){
+ // summary:
+ // gets the dom node for a given grid cell.
+ // inRowIndex: int
+ // grid row index
+ // returns: dom node for a given grid cell
+ return this.view.getCellNode(inRowIndex, this.index);
+ },
+ isFlex: function(){
+ var uw = this.unitWidth;
+ return uw && (uw=='auto' || uw.slice(-1)=='%');
+ },
+ // edit support
+ applyEdit: function(inValue, inRowIndex){
+ this.grid.edit.applyCellEdit(inValue, this, inRowIndex);
+ },
+ cancelEdit: function(inRowIndex){
+ this.grid.doCancelEdit(inRowIndex);
+ },
+ _onEditBlur: function(inRowIndex){
+ if(this.grid.edit.isEditCell(inRowIndex, this.index)){
+ //console.log('editor onblur', e);
+ this.grid.edit.apply();
+ }
+ },
+ registerOnBlur: function(inNode, inRowIndex){
+ if(this.commitOnBlur){
+ dojo.connect(inNode, "onblur", function(e){
+ // hack: if editor still thinks this editor is current some ms after it blurs, assume we've focused away from grid
+ setTimeout(dojo.hitch(this, "_onEditBlur", inRowIndex), 250);
+ });
+ }
+ }
+});
+
+}
diff --git a/includes/js/dojox/grid/_grid/drag.js b/includes/js/dojox/grid/_grid/drag.js
new file mode 100644
index 0000000..df086f9
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/drag.js
@@ -0,0 +1,113 @@
+if(!dojo._hasResource["dojox.grid._grid.drag"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._grid.drag"] = true;
+dojo.provide("dojox.grid._grid.drag");
+
+// summary:
+// utility functions for dragging as used in grid.
+// begin closure
+(function(){
+
+var dgdrag = dojox.grid.drag = {};
+
+dgdrag.dragging = false;
+dgdrag.hysteresis = 2;
+
+dgdrag.capture = function(inElement) {
+ //console.debug('dojox.grid.drag.capture');
+ if (inElement.setCapture)
+ inElement.setCapture();
+ else {
+ document.addEventListener("mousemove", inElement.onmousemove, true);
+ document.addEventListener("mouseup", inElement.onmouseup, true);
+ document.addEventListener("click", inElement.onclick, true);
+ }
+}
+
+dgdrag.release = function(inElement) {
+ //console.debug('dojox.grid.drag.release');
+ if(inElement.releaseCapture){
+ inElement.releaseCapture();
+ }else{
+ document.removeEventListener("click", inElement.onclick, true);
+ document.removeEventListener("mouseup", inElement.onmouseup, true);
+ document.removeEventListener("mousemove", inElement.onmousemove, true);
+ }
+}
+
+dgdrag.start = function(inElement, inOnDrag, inOnEnd, inEvent, inOnStart){
+ if(/*dgdrag.elt ||*/ !inElement || dgdrag.dragging){
+ console.debug('failed to start drag: bad input node or already dragging');
+ return;
+ }
+ dgdrag.dragging = true;
+ dgdrag.elt = inElement;
+ dgdrag.events = {
+ drag: inOnDrag || dojox.grid.nop,
+ end: inOnEnd || dojox.grid.nop,
+ start: inOnStart || dojox.grid.nop,
+ oldmove: inElement.onmousemove,
+ oldup: inElement.onmouseup,
+ oldclick: inElement.onclick
+ };
+ dgdrag.positionX = (inEvent && ('screenX' in inEvent) ? inEvent.screenX : false);
+ dgdrag.positionY = (inEvent && ('screenY' in inEvent) ? inEvent.screenY : false);
+ dgdrag.started = (dgdrag.position === false);
+ inElement.onmousemove = dgdrag.mousemove;
+ inElement.onmouseup = dgdrag.mouseup;
+ inElement.onclick = dgdrag.click;
+ dgdrag.capture(dgdrag.elt);
+}
+
+dgdrag.end = function(){
+ //console.debug("dojox.grid.drag.end");
+ dgdrag.release(dgdrag.elt);
+ dgdrag.elt.onmousemove = dgdrag.events.oldmove;
+ dgdrag.elt.onmouseup = dgdrag.events.oldup;
+ dgdrag.elt.onclick = dgdrag.events.oldclick;
+ dgdrag.elt = null;
+ try{
+ if(dgdrag.started){
+ dgdrag.events.end();
+ }
+ }finally{
+ dgdrag.dragging = false;
+ }
+}
+
+dgdrag.calcDelta = function(inEvent){
+ inEvent.deltaX = inEvent.screenX - dgdrag.positionX;
+ inEvent.deltaY = inEvent.screenY - dgdrag.positionY;
+}
+
+dgdrag.hasMoved = function(inEvent){
+ return Math.abs(inEvent.deltaX) + Math.abs(inEvent.deltaY) > dgdrag.hysteresis;
+}
+
+dgdrag.mousemove = function(inEvent){
+ inEvent = dojo.fixEvent(inEvent);
+ dojo.stopEvent(inEvent);
+ dgdrag.calcDelta(inEvent);
+ if((!dgdrag.started)&&(dgdrag.hasMoved(inEvent))){
+ dgdrag.events.start(inEvent);
+ dgdrag.started = true;
+ }
+ if(dgdrag.started){
+ dgdrag.events.drag(inEvent);
+ }
+}
+
+dgdrag.mouseup = function(inEvent){
+ //console.debug("dojox.grid.drag.mouseup");
+ dojo.stopEvent(dojo.fixEvent(inEvent));
+ dgdrag.end();
+}
+
+dgdrag.click = function(inEvent){
+ dojo.stopEvent(dojo.fixEvent(inEvent));
+ //dgdrag.end();
+}
+
+})();
+// end closure
+
+}
diff --git a/includes/js/dojox/grid/_grid/edit.js b/includes/js/dojox/grid/_grid/edit.js
new file mode 100644
index 0000000..d918423
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/edit.js
@@ -0,0 +1,238 @@
+if(!dojo._hasResource["dojox.grid._grid.edit"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._grid.edit"] = true;
+dojo.provide("dojox.grid._grid.edit");
+
+dojo.declare("dojox.grid.edit", null, {
+ // summary:
+ // Controls grid cell editing process. Owned by grid and used internally for editing.
+ constructor: function(inGrid){
+ // inGrid: dojox.Grid
+ // The dojox.Grid this editor should be attached to
+ this.grid = inGrid;
+ this.connections = [];
+ if(dojo.isIE){
+ this.connections.push(dojo.connect(document.body, "onfocus", dojo.hitch(this, "_boomerangFocus")));
+ }
+ },
+
+ info: {},
+
+ destroy: function(){
+ dojo.forEach(this.connections,dojo.disconnect);
+ },
+
+ cellFocus: function(inCell, inRowIndex){
+ // summary:
+ // Invoke editing when cell is focused
+ // inCell: cell object
+ // Grid cell object
+ // inRowIndex: Integer
+ // Grid row index
+ if(this.grid.singleClickEdit || this.isEditRow(inRowIndex)){
+ // if same row or quick editing, edit
+ this.setEditCell(inCell, inRowIndex);
+ }else{
+ // otherwise, apply any pending row edits
+ this.apply();
+ }
+ // if dynamic or static editing...
+ if(this.isEditing() || (inCell && (inCell.editor||0).alwaysOn)){
+ // let the editor focus itself as needed
+ this._focusEditor(inCell, inRowIndex);
+ }
+ },
+
+ rowClick: function(e){
+ if(this.isEditing() && !this.isEditRow(e.rowIndex)){
+ this.apply();
+ }
+ },
+
+ styleRow: function(inRow){
+ if(inRow.index == this.info.rowIndex){
+ inRow.customClasses += ' dojoxGrid-row-editing';
+ }
+ },
+
+ dispatchEvent: function(e){
+ var c = e.cell, ed = c && c.editor;
+ return ed && ed.dispatchEvent(e.dispatch, e);
+ },
+
+ // Editing
+ isEditing: function(){
+ // summary:
+ // Indicates editing state of the grid.
+ // returns: Boolean
+ // True if grid is actively editing
+ return this.info.rowIndex !== undefined;
+ },
+
+ isEditCell: function(inRowIndex, inCellIndex){
+ // summary:
+ // Indicates if the given cell is being edited.
+ // inRowIndex: Integer
+ // Grid row index
+ // inCellIndex: Integer
+ // Grid cell index
+ // returns: Boolean
+ // True if given cell is being edited
+ return (this.info.rowIndex === inRowIndex) && (this.info.cell.index == inCellIndex);
+ },
+
+ isEditRow: function(inRowIndex){
+ // summary:
+ // Indicates if the given row is being edited.
+ // inRowIndex: Integer
+ // Grid row index
+ // returns: Boolean
+ // True if given row is being edited
+ return this.info.rowIndex === inRowIndex;
+ },
+
+ setEditCell: function(inCell, inRowIndex){
+ // summary:
+ // Set the given cell to be edited
+ // inRowIndex: Integer
+ // Grid row index
+ // inCell: Object
+ // Grid cell object
+ if(!this.isEditCell(inRowIndex, inCell.index) && this.grid.canEdit(inCell, inRowIndex)){
+ this.start(inCell, inRowIndex, this.isEditRow(inRowIndex) || inCell.editor);
+ }
+ },
+
+ _focusEditor: function(inCell, inRowIndex){
+ dojox.grid.fire(inCell.editor, "focus", [inRowIndex]);
+ },
+
+ focusEditor: function(){
+ if(this.isEditing()){
+ this._focusEditor(this.info.cell, this.info.rowIndex);
+ }
+ },
+
+ // implement fix for focus boomerang effect on IE
+ _boomerangWindow: 500,
+ _shouldCatchBoomerang: function(){
+ return this._catchBoomerang > new Date().getTime();
+ },
+ _boomerangFocus: function(){
+ //console.log("_boomerangFocus");
+ if(this._shouldCatchBoomerang()){
+ // make sure we don't utterly lose focus
+ this.grid.focus.focusGrid();
+ // let the editor focus itself as needed
+ this.focusEditor();
+ // only catch once
+ this._catchBoomerang = 0;
+ }
+ },
+ _doCatchBoomerang: function(){
+ // give ourselves a few ms to boomerang IE focus effects
+ if(dojo.isIE){this._catchBoomerang = new Date().getTime() + this._boomerangWindow;}
+ },
+ // end boomerang fix API
+
+ start: function(inCell, inRowIndex, inEditing){
+ this.grid.beginUpdate();
+ this.editorApply();
+ if(this.isEditing() && !this.isEditRow(inRowIndex)){
+ this.applyRowEdit();
+ this.grid.updateRow(inRowIndex);
+ }
+ if(inEditing){
+ this.info = { cell: inCell, rowIndex: inRowIndex };
+ this.grid.doStartEdit(inCell, inRowIndex);
+ this.grid.updateRow(inRowIndex);
+ }else{
+ this.info = {};
+ }
+ this.grid.endUpdate();
+ // make sure we don't utterly lose focus
+ this.grid.focus.focusGrid();
+ // let the editor focus itself as needed
+ this._focusEditor(inCell, inRowIndex);
+ // give ourselves a few ms to boomerang IE focus effects
+ this._doCatchBoomerang();
+ },
+
+ _editorDo: function(inMethod){
+ var c = this.info.cell
+ //c && c.editor && c.editor[inMethod](c, this.info.rowIndex);
+ c && c.editor && c.editor[inMethod](this.info.rowIndex);
+ },
+
+ editorApply: function(){
+ this._editorDo("apply");
+ },
+
+ editorCancel: function(){
+ this._editorDo("cancel");
+ },
+
+ applyCellEdit: function(inValue, inCell, inRowIndex){
+ if(this.grid.canEdit(inCell, inRowIndex)){
+ this.grid.doApplyCellEdit(inValue, inRowIndex, inCell.fieldIndex);
+ }
+ },
+
+ applyRowEdit: function(){
+ this.grid.doApplyEdit(this.info.rowIndex);
+ },
+
+ apply: function(){
+ // summary:
+ // Apply a grid edit
+ if(this.isEditing()){
+ this.grid.beginUpdate();
+ this.editorApply();
+ this.applyRowEdit();
+ this.info = {};
+ this.grid.endUpdate();
+ this.grid.focus.focusGrid();
+ this._doCatchBoomerang();
+ }
+ },
+
+ cancel: function(){
+ // summary:
+ // Cancel a grid edit
+ if(this.isEditing()){
+ this.grid.beginUpdate();
+ this.editorCancel();
+ this.info = {};
+ this.grid.endUpdate();
+ this.grid.focus.focusGrid();
+ this._doCatchBoomerang();
+ }
+ },
+
+ save: function(inRowIndex, inView){
+ // summary:
+ // Save the grid editing state
+ // inRowIndex: Integer
+ // Grid row index
+ // inView: Object
+ // Grid view
+ var c = this.info.cell;
+ if(this.isEditRow(inRowIndex) && (!inView || c.view==inView) && c.editor){
+ c.editor.save(c, this.info.rowIndex);
+ }
+ },
+
+ restore: function(inView, inRowIndex){
+ // summary:
+ // Restores the grid editing state
+ // inRowIndex: Integer
+ // Grid row index
+ // inView: Object
+ // Grid view
+ var c = this.info.cell;
+ if(this.isEditRow(inRowIndex) && c.view == inView && c.editor){
+ c.editor.restore(c, this.info.rowIndex);
+ }
+ }
+});
+
+}
diff --git a/includes/js/dojox/grid/_grid/focus.js b/includes/js/dojox/grid/_grid/focus.js
new file mode 100644
index 0000000..8761042
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/focus.js
@@ -0,0 +1,207 @@
+if(!dojo._hasResource["dojox.grid._grid.focus"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._grid.focus"] = true;
+dojo.provide("dojox.grid._grid.focus");
+
+// focus management
+dojo.declare("dojox.grid.focus", null, {
+ // summary:
+ // Controls grid cell focus. Owned by grid and used internally for focusing.
+ // Note: grid cell actually receives keyboard input only when cell is being edited.
+ constructor: function(inGrid){
+ this.grid = inGrid;
+ this.cell = null;
+ this.rowIndex = -1;
+ dojo.connect(this.grid.domNode, "onfocus", this, "doFocus");
+ },
+ tabbingOut: false,
+ focusClass: "dojoxGrid-cell-focus",
+ focusView: null,
+ initFocusView: function(){
+ this.focusView = this.grid.views.getFirstScrollingView();
+ },
+ isFocusCell: function(inCell, inRowIndex){
+ // summary:
+ // states if the given cell is focused
+ // inCell: object
+ // grid cell object
+ // inRowIndex: int
+ // grid row index
+ // returns:
+ // true of the given grid cell is focused
+ return (this.cell == inCell) && (this.rowIndex == inRowIndex);
+ },
+ isLastFocusCell: function(){
+ return (this.rowIndex == this.grid.rowCount-1) && (this.cell.index == this.grid.layout.cellCount-1);
+ },
+ isFirstFocusCell: function(){
+ return (this.rowIndex == 0) && (this.cell.index == 0);
+ },
+ isNoFocusCell: function(){
+ return (this.rowIndex < 0) || !this.cell;
+ },
+ _focusifyCellNode: function(inBork){
+ var n = this.cell && this.cell.getNode(this.rowIndex);
+ if(n){
+ dojo.toggleClass(n, this.focusClass, inBork);
+ if (inBork){
+ this.scrollIntoView();
+ try{
+ if(!this.grid.edit.isEditing())
+ dojox.grid.fire(n, "focus");
+ }catch(e){}
+ }
+ }
+ },
+ scrollIntoView: function() {
+ if(!this.cell){
+ return;
+ }
+ var
+ c = this.cell,
+ s = c.view.scrollboxNode,
+ sr = {
+ w: s.clientWidth,
+ l: s.scrollLeft,
+ t: s.scrollTop,
+ h: s.clientHeight
+ },
+ n = c.getNode(this.rowIndex),
+ r = c.view.getRowNode(this.rowIndex),
+ rt = this.grid.scroller.findScrollTop(this.rowIndex);
+ // place cell within horizontal view
+ if(n.offsetLeft + n.offsetWidth > sr.l + sr.w){
+ s.scrollLeft = n.offsetLeft + n.offsetWidth - sr.w;
+ }else if(n.offsetLeft < sr.l){
+ s.scrollLeft = n.offsetLeft;
+ }
+ // place cell within vertical view
+ if(rt + r.offsetHeight > sr.t + sr.h){
+ this.grid.setScrollTop(rt + r.offsetHeight - sr.h);
+ }else if(rt < sr.t){
+ this.grid.setScrollTop(rt);
+ }
+ },
+ styleRow: function(inRow){
+ return;
+ },
+ setFocusIndex: function(inRowIndex, inCellIndex){
+ // summary:
+ // focuses the given grid cell
+ // inRowIndex: int
+ // grid row index
+ // inCellIndex: int
+ // grid cell index
+ this.setFocusCell(this.grid.getCell(inCellIndex), inRowIndex);
+ },
+ setFocusCell: function(inCell, inRowIndex){
+ // summary:
+ // focuses the given grid cell
+ // inCell: object
+ // grid cell object
+ // inRowIndex: int
+ // grid row index
+ if(inCell && !this.isFocusCell(inCell, inRowIndex)){
+ this.tabbingOut = false;
+ this.focusGridView();
+ this._focusifyCellNode(false);
+ this.cell = inCell;
+ this.rowIndex = inRowIndex;
+ this._focusifyCellNode(true);
+ }
+ // even if this cell isFocusCell, the document focus may need to be rejiggered
+ // call opera on delay to prevent keypress from altering focus
+ if(dojo.isOpera){
+ setTimeout(dojo.hitch(this.grid, 'onCellFocus', this.cell, this.rowIndex), 1);
+ }else{
+ this.grid.onCellFocus(this.cell, this.rowIndex);
+ }
+ },
+ next: function(){
+ // summary:
+ // focus next grid cell
+ var row=this.rowIndex, col=this.cell.index+1, cc=this.grid.layout.cellCount-1, rc=this.grid.rowCount-1;
+ if(col > cc){
+ col = 0;
+ row++;
+ }
+ if(row > rc){
+ col = cc;
+ row = rc;
+ }
+ this.setFocusIndex(row, col);
+ },
+ previous: function(){
+ // summary:
+ // focus previous grid cell
+ var row=(this.rowIndex || 0), col=(this.cell.index || 0) - 1;
+ if(col < 0){
+ col = this.grid.layout.cellCount-1;
+ row--;
+ }
+ if(row < 0){
+ row = 0;
+ col = 0;
+ }
+ this.setFocusIndex(row, col);
+ },
+ move: function(inRowDelta, inColDelta) {
+ // summary:
+ // focus grid cell based on position relative to current focus
+ // inRowDelta: int
+ // vertical distance from current focus
+ // inColDelta: int
+ // horizontal distance from current focus
+ var
+ rc = this.grid.rowCount-1,
+ cc = this.grid.layout.cellCount-1,
+ r = this.rowIndex,
+ i = this.cell.index,
+ row = Math.min(rc, Math.max(0, r+inRowDelta)),
+ col = Math.min(cc, Math.max(0, i+inColDelta));
+ this.setFocusIndex(row, col);
+ if(inRowDelta){
+ this.grid.updateRow(r);
+ }
+ },
+ previousKey: function(e){
+ if(this.isFirstFocusCell()){
+ this.tabOut(this.grid.domNode);
+ }else{
+ dojo.stopEvent(e);
+ this.previous();
+ }
+ },
+ nextKey: function(e) {
+ if(this.isLastFocusCell()){
+ this.tabOut(this.grid.lastFocusNode);
+ }else{
+ dojo.stopEvent(e);
+ this.next();
+ }
+ },
+ tabOut: function(inFocusNode){
+ this.tabbingOut = true;
+ inFocusNode.focus();
+ },
+ focusGridView: function(){
+ dojox.grid.fire(this.focusView, "focus");
+ },
+ focusGrid: function(inSkipFocusCell){
+ this.focusGridView();
+ this._focusifyCellNode(true);
+ },
+ doFocus: function(e){
+ // trap focus only for grid dom node
+ if(e && e.target != e.currentTarget){
+ return;
+ }
+ // do not focus for scrolling if grid is about to blur
+ if(!this.tabbingOut && this.isNoFocusCell()){
+ // establish our virtual-focus, if necessary
+ this.setFocusIndex(0, 0);
+ }
+ this.tabbingOut = false;
+ }
+});
+
+}
diff --git a/includes/js/dojox/grid/_grid/images/grid_dx_gradient.gif b/includes/js/dojox/grid/_grid/images/grid_dx_gradient.gif
new file mode 100644
index 0000000..57f67ba
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/images/grid_dx_gradient.gif
Binary files differ
diff --git a/includes/js/dojox/grid/_grid/images/grid_sort_down.gif b/includes/js/dojox/grid/_grid/images/grid_sort_down.gif
new file mode 100644
index 0000000..7a73f82
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/images/grid_sort_down.gif
Binary files differ
diff --git a/includes/js/dojox/grid/_grid/images/grid_sort_up.gif b/includes/js/dojox/grid/_grid/images/grid_sort_up.gif
new file mode 100644
index 0000000..9452da0
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/images/grid_sort_up.gif
Binary files differ
diff --git a/includes/js/dojox/grid/_grid/images/tabEnabled_rotated.png b/includes/js/dojox/grid/_grid/images/tabEnabled_rotated.png
new file mode 100644
index 0000000..e326abd
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/images/tabEnabled_rotated.png
Binary files differ
diff --git a/includes/js/dojox/grid/_grid/images/tabHover_rotated.png b/includes/js/dojox/grid/_grid/images/tabHover_rotated.png
new file mode 100644
index 0000000..1a30e10
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/images/tabHover_rotated.png
Binary files differ
diff --git a/includes/js/dojox/grid/_grid/layout.js b/includes/js/dojox/grid/_grid/layout.js
new file mode 100644
index 0000000..128f486
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/layout.js
@@ -0,0 +1,75 @@
+if(!dojo._hasResource["dojox.grid._grid.layout"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._grid.layout"] = true;
+dojo.provide("dojox.grid._grid.layout");
+dojo.require("dojox.grid._grid.cell");
+
+dojo.declare("dojox.grid.layout", null, {
+ // summary:
+ // Controls grid cell layout. Owned by grid and used internally.
+ constructor: function(inGrid){
+ this.grid = inGrid;
+ },
+ // flat array of grid cells
+ cells: [],
+ // structured array of grid cells
+ structure: null,
+ // default cell width
+ defaultWidth: '6em',
+ // methods
+ setStructure: function(inStructure){
+ this.fieldIndex = 0;
+ this.cells = [];
+ var s = this.structure = [];
+ for(var i=0, viewDef, rows; (viewDef=inStructure[i]); i++){
+ s.push(this.addViewDef(viewDef));
+ }
+ this.cellCount = this.cells.length;
+ },
+ addViewDef: function(inDef){
+ this._defaultCellProps = inDef.defaultCell || {};
+ return dojo.mixin({}, inDef, {rows: this.addRowsDef(inDef.rows || inDef.cells)});
+ },
+ addRowsDef: function(inDef){
+ var result = [];
+ for(var i=0, row; inDef && (row=inDef[i]); i++){
+ result.push(this.addRowDef(i, row));
+ }
+ return result;
+ },
+ addRowDef: function(inRowIndex, inDef){
+ var result = [];
+ for(var i=0, def, cell; (def=inDef[i]); i++){
+ cell = this.addCellDef(inRowIndex, i, def);
+ result.push(cell);
+ this.cells.push(cell);
+ }
+ return result;
+ },
+ addCellDef: function(inRowIndex, inCellIndex, inDef){
+ var w = 0;
+ if(inDef.colSpan > 1){
+ w = 0;
+ }else if(!isNaN(inDef.width)){
+ w = inDef.width + "em";
+ }else{
+ w = inDef.width || this.defaultWidth;
+ }
+ // fieldIndex progresses linearly from the last indexed field
+ // FIXME: support generating fieldIndex based a text field name (probably in Grid)
+ var fieldIndex = inDef.field != undefined ? inDef.field : (inDef.get ? -1 : this.fieldIndex);
+ if((inDef.field != undefined) || !inDef.get){
+ this.fieldIndex = (inDef.field > -1 ? inDef.field : this.fieldIndex) + 1;
+ }
+ return new dojox.grid.cell(
+ dojo.mixin({}, this._defaultCellProps, inDef, {
+ grid: this.grid,
+ subrow: inRowIndex,
+ layoutIndex: inCellIndex,
+ index: this.cells.length,
+ fieldIndex: fieldIndex,
+ unitWidth: w
+ }));
+ }
+});
+
+}
diff --git a/includes/js/dojox/grid/_grid/lib.js b/includes/js/dojox/grid/_grid/lib.js
new file mode 100644
index 0000000..3644dbc
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/lib.js
@@ -0,0 +1,254 @@
+if(!dojo._hasResource["dojox.grid._grid.lib"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._grid.lib"] = true;
+dojo.provide("dojox.grid._grid.lib");
+// summary: grid utility library
+dojo.mixin(dojox.grid,{
+
+ na: '...',
+
+ nop: function(){
+ // summary: a null function?
+ },
+
+ getTdIndex: function(td){
+ return td.cellIndex >=0 ? td.cellIndex : dojo.indexOf(td.parentNode.cells, td);
+ },
+
+ getTrIndex: function(tr){
+ return tr.rowIndex >=0 ? tr.rowIndex : dojo.indexOf(tr.parentNode.childNodes, tr);
+ },
+
+ getTr: function(rowOwner, index){
+ return rowOwner && ((rowOwner.rows||0)[index] || rowOwner.childNodes[index]);
+ },
+
+ getTd: function(rowOwner, rowIndex, cellIndex){
+ return (dojox.grid.getTr(inTable, rowIndex)||0)[cellIndex];
+ },
+
+ findTable: function(node){
+ for (var n=node; n && n.tagName!='TABLE'; n=n.parentNode);
+ return n;
+ },
+
+ ascendDom: function(inNode, inWhile){
+ for (var n=inNode; n && inWhile(n); n=n.parentNode);
+ return n;
+ },
+
+ makeNotTagName: function(inTagName){
+ var name = inTagName.toUpperCase();
+ return function(node){ return node.tagName != name; };
+ },
+
+ fire: function(ob, ev, args){
+ var fn = ob && ev && ob[ev];
+ return fn && (args ? fn.apply(ob, args) : ob[ev]());
+ },
+
+ // from lib.js
+ setStyleText: function(inNode, inStyleText){
+ if(inNode.style.cssText == undefined){
+ inNode.setAttribute("style", inStyleText);
+ }else{
+ inNode.style.cssText = inStyleText;
+ }
+ },
+
+ getStyleText: function(inNode, inStyleText){
+ return (inNode.style.cssText == undefined ? inNode.getAttribute("style") : inNode.style.cssText);
+ },
+
+ setStyle: function(inElement, inStyle, inValue){
+ if(inElement && inElement.style[inStyle] != inValue){
+ inElement.style[inStyle] = inValue;
+ }
+ },
+
+ setStyleHeightPx: function(inElement, inHeight){
+ if(inHeight >= 0){
+ dojox.grid.setStyle(inElement, 'height', inHeight + 'px');
+ }
+ },
+
+ mouseEvents: [ 'mouseover', 'mouseout', /*'mousemove',*/ 'mousedown', 'mouseup', 'click', 'dblclick', 'contextmenu' ],
+
+ keyEvents: [ 'keyup', 'keydown', 'keypress' ],
+
+ funnelEvents: function(inNode, inObject, inMethod, inEvents){
+ var evts = (inEvents ? inEvents : dojox.grid.mouseEvents.concat(dojox.grid.keyEvents));
+ for (var i=0, l=evts.length; i<l; i++){
+ dojo.connect(inNode, 'on' + evts[i], inObject, inMethod);
+ }
+ },
+
+ removeNode: function(inNode){
+ inNode = dojo.byId(inNode);
+ inNode && inNode.parentNode && inNode.parentNode.removeChild(inNode);
+ return inNode;
+ },
+
+ getScrollbarWidth: function(){
+ if(this._scrollBarWidth){
+ return this._scrollBarWidth;
+ }
+ this._scrollBarWidth = 18;
+ try{
+ var e = document.createElement("div");
+ e.style.cssText = "top:0;left:0;width:100px;height:100px;overflow:scroll;position:absolute;visibility:hidden;";
+ document.body.appendChild(e);
+ this._scrollBarWidth = e.offsetWidth - e.clientWidth;
+ document.body.removeChild(e);
+ delete e;
+ }catch (ex){}
+ return this._scrollBarWidth;
+ },
+
+ // needed? dojo has _getProp
+ getRef: function(name, create, context){
+ var obj=context||dojo.global, parts=name.split("."), prop=parts.pop();
+ for(var i=0, p; obj&&(p=parts[i]); i++){
+ obj = (p in obj ? obj[p] : (create ? obj[p]={} : undefined));
+ }
+ return { obj: obj, prop: prop };
+ },
+
+ getProp: function(name, create, context){
+ with(dojox.grid.getRef(name, create, context)){
+ return (obj)&&(prop)&&(prop in obj ? obj[prop] : (create ? obj[prop]={} : undefined));
+ }
+ },
+
+ indexInParent: function(inNode){
+ var i=0, n, p=inNode.parentNode;
+ while((n = p.childNodes[i++])){
+ if(n == inNode){
+ return i - 1;
+ }
+ }
+ return -1;
+ },
+
+ cleanNode: function(inNode){
+ if(!inNode){
+ return;
+ }
+ var filter = function(inW){
+ return inW.domNode && dojo.isDescendant(inW.domNode, inNode, true);
+ }
+ var ws = dijit.registry.filter(filter);
+ for(var i=0, w; (w=ws[i]); i++){
+ w.destroy();
+ }
+ delete ws;
+ },
+
+ getTagName: function(inNodeOrId){
+ var node = dojo.byId(inNodeOrId);
+ return (node && node.tagName ? node.tagName.toLowerCase() : '');
+ },
+
+ nodeKids: function(inNode, inTag){
+ var result = [];
+ var i=0, n;
+ while((n = inNode.childNodes[i++])){
+ if(dojox.grid.getTagName(n) == inTag){
+ result.push(n);
+ }
+ }
+ return result;
+ },
+
+ divkids: function(inNode){
+ return dojox.grid.nodeKids(inNode, 'div');
+ },
+
+ focusSelectNode: function(inNode){
+ try{
+ dojox.grid.fire(inNode, "focus");
+ dojox.grid.fire(inNode, "select");
+ }catch(e){// IE sux bad
+ }
+ },
+
+ whenIdle: function(/*inContext, inMethod, args ...*/){
+ setTimeout(dojo.hitch.apply(dojo, arguments), 0);
+ },
+
+ arrayCompare: function(inA, inB){
+ for(var i=0,l=inA.length; i<l; i++){
+ if(inA[i] != inB[i]){return false;}
+ }
+ return (inA.length == inB.length);
+ },
+
+ arrayInsert: function(inArray, inIndex, inValue){
+ if(inArray.length <= inIndex){
+ inArray[inIndex] = inValue;
+ }else{
+ inArray.splice(inIndex, 0, inValue);
+ }
+ },
+
+ arrayRemove: function(inArray, inIndex){
+ inArray.splice(inIndex, 1);
+ },
+
+ arraySwap: function(inArray, inI, inJ){
+ var cache = inArray[inI];
+ inArray[inI] = inArray[inJ];
+ inArray[inJ] = cache;
+ },
+
+ initTextSizePoll: function(inInterval) {
+ var f = document.createElement("div");
+ with (f.style) {
+ top = "0px";
+ left = "0px";
+ position = "absolute";
+ visibility = "hidden";
+ }
+ f.innerHTML = "TheQuickBrownFoxJumpedOverTheLazyDog";
+ document.body.appendChild(f);
+ var fw = f.offsetWidth;
+ var job = function() {
+ if (f.offsetWidth != fw) {
+ fw = f.offsetWidth;
+ dojox.grid.textSizeChanged();
+ }
+ }
+ window.setInterval(job, inInterval||200);
+ dojox.grid.initTextSizePoll = dojox.grid.nop;
+ },
+
+ textSizeChanged: function() {
+
+ }
+});
+
+dojox.grid.jobs = {
+
+ cancel: function(inHandle){
+ if(inHandle){
+ window.clearTimeout(inHandle);
+ }
+ },
+
+ jobs: [],
+
+ job: function(inName, inDelay, inJob){
+ dojox.grid.jobs.cancelJob(inName);
+ var job = function(){
+ delete dojox.grid.jobs.jobs[inName];
+ inJob();
+ }
+ dojox.grid.jobs.jobs[inName] = setTimeout(job, inDelay);
+ },
+
+ cancelJob: function(inName){
+ dojox.grid.jobs.cancel(dojox.grid.jobs.jobs[inName]);
+ }
+
+}
+
+}
diff --git a/includes/js/dojox/grid/_grid/nihiloGrid.css b/includes/js/dojox/grid/_grid/nihiloGrid.css
new file mode 100644
index 0000000..ba9f39d
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/nihiloGrid.css
@@ -0,0 +1,211 @@
+.nihilo .dojoxGrid {
+ position: relative;
+ background-color: #e9e9e9;
+ font-size: 0.85em;
+ -moz-outline-style: none;
+ outline: none;
+ overflow: hidden;
+ height: 0;
+}
+.nihilo .dojoxGrid table {
+ padding: 0;
+}
+.nihilo .dojoxGrid td {
+ -moz-outline: none;
+}
+.nihilo .dojoxGrid-master-header {
+ position: relative;
+}
+.nihilo .dojoxGrid-master-view {
+ position: relative;
+}
+.nihilo .dojoxGrid-view {
+ position: absolute;
+ overflow: hidden;
+}
+.nihilo .dojoxGrid-header {
+ position: absolute;
+ overflow: hidden;
+}
+.nihilo .dojoxGrid-header {
+ background-color: #e9e9e9;
+}
+.nihilo .dojoxGrid-header table {
+ text-align: center;
+}
+.nihilo .dojoxGrid-header .dojoxGrid-cell-content {
+ text-align: center;
+}
+.nihilo .dojoxGrid-header .dojoxGrid-cell {
+ border: 1px solid transparent;
+
+ border-color: white #ACA899 #919191 white;
+ background: url(../../../dijit/themes/nihilo/images/titleBar.png) #e9e9e9 repeat-x top;
+ padding-bottom: 2px;
+ color: #000 !important;
+}
+.nihilo .dojoxGrid-header .dojoxGrid-cell-over {
+ background: url(../../../dijit/themes/nihilo/images/titleBarActive.png) #e9e9e9 repeat-x top;
+}
+.nihilo .dojoxGrid-sort-down {
+ background: url(images/grid_sort_down.gif) right no-repeat;
+ padding-left: 0px;
+ margin-left: 0px;
+}
+.nihilo .dojoxGrid-sort-up {
+ background: url(images/grid_sort_up.gif) right no-repeat;
+ padding-left: 0px;
+ margin-left: 0px;
+}
+.nihilo .gridArrowButtonChar {
+ display:none !important;
+}
+.dijit_a11y .gridArrowButtonChar {
+ display:inline !important;
+}
+.nihilo .dojoxGrid-scrollbox {
+ position: relative;
+ overflow: scroll;
+ background-color: #fefefe;
+ width: 100%;
+}
+.nihilo .dojoxGrid-content {
+ position: relative;
+ overflow: hidden;
+ -moz-outline-style: none;
+ outline: none;
+}
+.nihilo .dojoxGrid-rowbar {
+ border: none;
+
+ background: url(images/titleBar.png) #e9e9e9 repeat-y right;
+ border-right: 1px solid #cccccc;
+ padding: 0px;
+}
+.nihilo .dojoxGrid-rowbar-inner {
+ border: none;
+ border-bottom: 1px solid #cccccc;
+}
+.nihilo .dojoxGrid-rowbar-over {
+ background: url(images/titleBarActive.png) #e9e9e9 repeat-y right;
+}
+.nihilo .dojoxGrid-rowbar-selected {
+ background-color: #D9E8F9;
+ background-image: none;
+ background: url(../../../dijit/themes/nihilo/images/titleBar.png) #dddddd repeat-x top;
+ border-right: 1px solid #cccccc;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+.nihilo .dojoxGrid-row {
+ position: relative;
+ width: 9000em;
+}
+.nihilo .dojoxGrid-row {
+ border: none;
+ border-left: none;
+ border-right: none;
+ background-color: white;
+ border-top: none;
+}
+.nihilo .dojoxGrid-row-over {
+ border-top-color: #cccccc;
+ border-bottom-color: #cccccc;
+}
+.nihilo .dojoxGrid-row-over .dojoxGrid-cell {
+ background-color: #ffe284;
+}
+.nihilo .dojoxGrid-row-odd {
+ background-color: #f2f5f9;
+
+}
+.nihilo .dojoxGrid-row-selected {
+ background-color: #aec7e3;
+}
+.nihilo .dojoxGrid-row-table {
+ table-layout: fixed;
+ width: 0;
+ border-collapse: collapse;
+}
+.nihilo .dojoxGrid-invisible {
+ visibility: hidden;
+}
+.nihilo .Xdojo-ie .dojoxGrid-invisible {
+ display: none;
+}
+.nihilo .dojoxGrid-invisible td, .dojoxGrid-header .dojoxGrid-invisible td {
+ border-top-width: 0;
+ border-bottom-width: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ height: 0;
+ overflow: hidden;
+}
+.nihilo .dojoxGrid-cell {
+ border: 1px dotted #D5CDB5;
+ padding: 3px 3px 3px 3px;
+ text-align: left;
+ overflow: hidden;
+}
+.dj_ie6 .nihilo .dojoxGrid-cell {
+ border: 1px solid white;
+ border-right: 1px solid #D5CDB5;
+}
+.nihilo .dojoxGrid-cell-focus {
+ border: 1px dotted #a6a6a6;
+}
+.nihilo .dojoxGrid-cell-over {
+ border: 1px dotted #a6a6a6;
+}
+.nihilo .dojoxGrid-cell-focus.dojoxGrid-cell-over {
+ border: 1px dotted #595959;
+}
+.nihilo .dojoxGrid-cell-clip {
+ width: 100%;
+ overflow: hidden;
+ white-space:nowrap;
+ text-overflow: ellipsis;
+}
+.nihilo .dojoxGrid-row-editing td {
+
+ background-color: #ffe284;
+
+}
+.nihilo .dojoxGrid-row-inserting td {
+ background-color: #F4FFF4;
+}
+.nihilo .dojoxGrid-row-inflight td {
+ background-color: #F2F7B7;
+}
+.nihilo .dojoxGrid-row-error td {
+ background-color: #F8B8B6;
+}
+.nihilo .dojoxGrid-input,
+.nihilo .dojoxGrid-select,
+.nihilo .dojoxGrid-textarea {
+ margin: 0;
+ padding: 0px;
+ border-style: none;
+ width: 100%;
+ font-size: 100%;
+ font-family: inherit;
+}
+.dojoxGrid-hidden-focus {
+ position: absolute;
+ left: -1000px;
+ top: -1000px;
+ height: 0px, width: 0px;
+}
+.dijit_a11y .dojoxGrid-rowbar-selected {
+ border-top: 1px solid white;
+ border-bottom: 1px dashed black;
+ border-top: 0;
+ background: none;
+}
+.dijit_a11y .dojoxGrid-rowbar-selected .dojoxGrid-rowbar-inner {
+ border: 0;
+ border-top: 1px solid white;
+}
+.dijit_a11y .dojoxGrid-row-selected {
+ border-bottom: 1px dashed black;
+}
diff --git a/includes/js/dojox/grid/_grid/nihiloGrid.css.commented.css b/includes/js/dojox/grid/_grid/nihiloGrid.css.commented.css
new file mode 100644
index 0000000..e50697d
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/nihiloGrid.css.commented.css
@@ -0,0 +1,275 @@
+.nihilo .dojoxGrid {
+ position: relative;
+ background-color: #e9e9e9;
+ font-size: 0.85em; /* inherit font-family from dojo.css */
+ -moz-outline-style: none;
+ outline: none;
+ overflow: hidden;
+ height: 0;
+}
+
+.nihilo .dojoxGrid table {
+ padding: 0;
+}
+
+.nihilo .dojoxGrid td {
+ -moz-outline: none;
+}
+
+/* master header */
+
+.nihilo .dojoxGrid-master-header {
+ position: relative;
+}
+
+/* master view */
+
+.nihilo .dojoxGrid-master-view {
+ position: relative;
+}
+
+/* views */
+
+.nihilo .dojoxGrid-view {
+ position: absolute;
+ overflow: hidden;
+}
+
+/* header */
+
+.nihilo .dojoxGrid-header {
+ position: absolute;
+ overflow: hidden;
+}
+
+.nihilo .dojoxGrid-header {
+ background-color: #e9e9e9;
+}
+
+.nihilo .dojoxGrid-header table {
+ text-align: center;
+}
+
+.nihilo .dojoxGrid-header .dojoxGrid-cell-content {
+ text-align: center;
+}
+
+.nihilo .dojoxGrid-header .dojoxGrid-cell {
+ border: 1px solid transparent;
+ /* border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB; */
+ border-color: white #ACA899 #919191 white;
+ background: url(../../../dijit/themes/nihilo/images/titleBar.png) #e9e9e9 repeat-x top;
+ padding-bottom: 2px;
+ color: #000 !important;
+}
+
+.nihilo .dojoxGrid-header .dojoxGrid-cell-over {
+ background: url(../../../dijit/themes/nihilo/images/titleBarActive.png) #e9e9e9 repeat-x top;
+}
+
+.nihilo .dojoxGrid-sort-down {
+ background: url(images/grid_sort_down.gif) right no-repeat;
+ padding-left: 0px;
+ margin-left: 0px;
+}
+
+.nihilo .dojoxGrid-sort-up {
+ background: url(images/grid_sort_up.gif) right no-repeat;
+ padding-left: 0px;
+ margin-left: 0px;
+}
+
+.nihilo .gridArrowButtonChar {
+ display:none !important;
+}
+.dijit_a11y .gridArrowButtonChar {
+ display:inline !important;
+}
+
+/* content */
+
+.nihilo .dojoxGrid-scrollbox {
+ position: relative;
+ overflow: scroll;
+ background-color: #fefefe;
+ width: 100%;
+}
+
+.nihilo .dojoxGrid-content {
+ position: relative;
+ overflow: hidden;
+ -moz-outline-style: none;
+ outline: none;
+}
+
+/* rowbar */
+
+.nihilo .dojoxGrid-rowbar {
+ border: none;
+ /*
+ border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
+ */
+ background: url(images/titleBar.png) #e9e9e9 repeat-y right;
+ border-right: 1px solid #cccccc;
+ padding: 0px;
+}
+
+.nihilo .dojoxGrid-rowbar-inner {
+ border: none;
+ border-bottom: 1px solid #cccccc;
+}
+
+.nihilo .dojoxGrid-rowbar-over {
+ background: url(images/titleBarActive.png) #e9e9e9 repeat-y right;
+}
+
+.nihilo .dojoxGrid-rowbar-selected {
+ background-color: #D9E8F9;
+ background-image: none;
+ background: url(../../../dijit/themes/nihilo/images/titleBar.png) #dddddd repeat-x top;
+ border-right: 1px solid #cccccc;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+/* rows */
+
+.nihilo .dojoxGrid-row {
+ position: relative;
+ width: 9000em;
+}
+
+.nihilo .dojoxGrid-row {
+ border: none;
+ border-left: none;
+ border-right: none;
+ background-color: white;
+ border-top: none;
+}
+
+.nihilo .dojoxGrid-row-over {
+ border-top-color: #cccccc;
+ border-bottom-color: #cccccc;
+}
+
+.nihilo .dojoxGrid-row-over .dojoxGrid-cell {
+ background-color: #ffe284;
+}
+
+.nihilo .dojoxGrid-row-odd {
+ background-color: #f2f5f9;
+ /*background-color: #F9F7E8;*/
+}
+
+.nihilo .dojoxGrid-row-selected {
+ background-color: #aec7e3;
+}
+
+.nihilo .dojoxGrid-row-table {
+ table-layout: fixed;
+ width: 0;
+ border-collapse: collapse;
+}
+
+.nihilo .dojoxGrid-invisible {
+ visibility: hidden;
+}
+
+.nihilo .Xdojo-ie .dojoxGrid-invisible {
+ display: none;
+}
+
+.nihilo .dojoxGrid-invisible td, .dojoxGrid-header .dojoxGrid-invisible td {
+ border-top-width: 0;
+ border-bottom-width: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ height: 0;
+ overflow: hidden;
+}
+
+/* cells */
+
+.nihilo .dojoxGrid-cell {
+ border: 1px dotted #D5CDB5;
+ padding: 3px 3px 3px 3px;
+ text-align: left;
+ overflow: hidden;
+}
+
+.dj_ie6 .nihilo .dojoxGrid-cell {
+ border: 1px solid white;
+ border-right: 1px solid #D5CDB5;
+}
+
+.nihilo .dojoxGrid-cell-focus {
+ border: 1px dotted #a6a6a6;
+}
+
+.nihilo .dojoxGrid-cell-over {
+ border: 1px dotted #a6a6a6;
+}
+
+.nihilo .dojoxGrid-cell-focus.dojoxGrid-cell-over {
+ border: 1px dotted #595959;
+}
+
+.nihilo .dojoxGrid-cell-clip {
+ width: 100%;
+ overflow: hidden;
+ white-space:nowrap;
+ text-overflow: ellipsis;
+}
+
+/* editing */
+
+/* FIXME: these colors are off! */
+.nihilo .dojoxGrid-row-editing td {
+ /* background-color: #F4FFF4; */
+ background-color: #ffe284;
+ /* padding: 0px 3px 0px 3px; */
+}
+
+.nihilo .dojoxGrid-row-inserting td {
+ background-color: #F4FFF4;
+}
+.nihilo .dojoxGrid-row-inflight td {
+ background-color: #F2F7B7;
+}
+.nihilo .dojoxGrid-row-error td {
+ background-color: #F8B8B6;
+}
+
+.nihilo .dojoxGrid-input,
+.nihilo .dojoxGrid-select,
+.nihilo .dojoxGrid-textarea {
+ margin: 0;
+ padding: 0px;
+ border-style: none;
+ width: 100%;
+ font-size: 100%;
+ font-family: inherit;
+}
+
+.dojoxGrid-hidden-focus {
+ position: absolute;
+ left: -1000px;
+ top: -1000px;
+ height: 0px, width: 0px;
+}
+
+.dijit_a11y .dojoxGrid-rowbar-selected {
+ border-top: 1px solid white;
+ border-bottom: 1px dashed black;
+ border-top: 0;
+ background: none;
+}
+
+.dijit_a11y .dojoxGrid-rowbar-selected .dojoxGrid-rowbar-inner {
+ border: 0;
+ border-top: 1px solid white;
+}
+
+.dijit_a11y .dojoxGrid-row-selected {
+ border-bottom: 1px dashed black;
+}
diff --git a/includes/js/dojox/grid/_grid/publicEvents.js b/includes/js/dojox/grid/_grid/publicEvents.js
new file mode 100644
index 0000000..4abb038
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/publicEvents.js
@@ -0,0 +1,451 @@
+if(!dojo._hasResource["dojox.grid._grid.publicEvents"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._grid.publicEvents"] = true;
+dojo.provide("dojox.grid._grid.publicEvents");
+
+dojox.grid.publicEvents = {
+ // summary:
+ // VirtualGrid mixin that provides default implementations for grid events.
+ // description:
+ // Default ynthetic events dispatched for VirtualGrid. dojo.connect to events to
+ // retain default implementation or override them for custom handling.
+
+ // cellOverClass: String
+ // css class to apply to grid cells over which the cursor is placed.
+ cellOverClass: "dojoxGrid-cell-over",
+
+ onKeyEvent: function(e){
+ // summary: top level handler for Key Events
+ this.dispatchKeyEvent(e);
+ },
+
+ onContentEvent: function(e){
+ // summary: Top level handler for Content events
+ this.dispatchContentEvent(e);
+ },
+
+ onHeaderEvent: function(e){
+ // summary: Top level handler for header events
+ this.dispatchHeaderEvent(e);
+ },
+
+ onStyleRow: function(inRow){
+ // summary:
+ // Perform row styling on a given row. Called whenever row styling is updated.
+ //
+ // inRow: Object
+ // Object containing row state information: selected, true if the row is selcted; over:
+ // true of the mouse is over the row; odd: true if the row is odd. Use customClasses and
+ // customStyles to control row css classes and styles; both properties are strings.
+ //
+ // example: onStyleRow({ selected: true, over:true, odd:false })
+ with(inRow){
+ customClasses += (odd?" dojoxGrid-row-odd":"") + (selected?" dojoxGrid-row-selected":"") + (over?" dojoxGrid-row-over":"");
+ }
+ this.focus.styleRow(inRow);
+ this.edit.styleRow(inRow);
+ },
+
+ onKeyDown: function(e){
+ // summary:
+ // Grid key event handler. By default enter begins editing and applies edits, escape cancels and edit,
+ // tab, shift-tab, and arrow keys move grid cell focus.
+ if(e.altKey || e.ctrlKey || e.metaKey){
+ return;
+ }
+ var dk = dojo.keys;
+ switch(e.keyCode){
+ case dk.ESCAPE:
+ this.edit.cancel();
+ break;
+ case dk.ENTER:
+ if(!e.shiftKey){
+ var isEditing = this.edit.isEditing();
+ this.edit.apply();
+ if(!isEditing){
+ this.edit.setEditCell(this.focus.cell, this.focus.rowIndex);
+ }
+ }
+ break;
+ case dk.TAB:
+ this.focus[e.shiftKey ? 'previousKey' : 'nextKey'](e);
+ break;
+ case dk.LEFT_ARROW:
+ case dk.RIGHT_ARROW:
+ if(!this.edit.isEditing()){
+ dojo.stopEvent(e);
+ var offset = (e.keyCode == dk.LEFT_ARROW) ? 1 : -1;
+ if(dojo._isBodyLtr()){ offset *= -1; }
+ this.focus.move(0, offset);
+ }
+ break;
+ case dk.UP_ARROW:
+ if(!this.edit.isEditing() && this.focus.rowIndex != 0){
+ dojo.stopEvent(e);
+ this.focus.move(-1, 0);
+ }
+ break;
+ case dk.DOWN_ARROW:
+ if(!this.edit.isEditing() && this.focus.rowIndex+1 != this.model.count){
+ dojo.stopEvent(e);
+ this.focus.move(1, 0);
+ }
+ break;
+ case dk.PAGE_UP:
+ if(!this.edit.isEditing() && this.focus.rowIndex != 0){
+ dojo.stopEvent(e);
+ if(this.focus.rowIndex != this.scroller.firstVisibleRow+1){
+ this.focus.move(this.scroller.firstVisibleRow-this.focus.rowIndex, 0);
+ }else{
+ this.setScrollTop(this.scroller.findScrollTop(this.focus.rowIndex-1));
+ this.focus.move(this.scroller.firstVisibleRow-this.scroller.lastVisibleRow+1, 0);
+ }
+ }
+ break;
+ case dk.PAGE_DOWN:
+ if(!this.edit.isEditing() && this.focus.rowIndex+1 != this.model.count){
+ dojo.stopEvent(e);
+ if(this.focus.rowIndex != this.scroller.lastVisibleRow-1){
+ this.focus.move(this.scroller.lastVisibleRow-this.focus.rowIndex-1, 0);
+ }else{
+ this.setScrollTop(this.scroller.findScrollTop(this.focus.rowIndex+1));
+ this.focus.move(this.scroller.lastVisibleRow-this.scroller.firstVisibleRow-1, 0);
+ }
+ }
+ break;
+ }
+ },
+
+ onMouseOver: function(e){
+ // summary:
+ // Event fired when mouse is over the grid.
+ // e: Event
+ // Decorated event object contains reference to grid, cell, and rowIndex
+ e.rowIndex == -1 ? this.onHeaderCellMouseOver(e) : this.onCellMouseOver(e);
+ },
+
+ onMouseOut: function(e){
+ // summary:
+ // Event fired when mouse moves out of the grid.
+ // e: Event
+ // Decorated event object that contains reference to grid, cell, and rowIndex
+ e.rowIndex == -1 ? this.onHeaderCellMouseOut(e) : this.onCellMouseOut(e);
+ },
+
+ onMouseDown: function(e){
+ // summary:
+ // Event fired when mouse is down inside grid.
+ // e: Event
+ // Decorated event object that contains reference to grid, cell, and rowIndex
+ e.rowIndex == -1 ? this.onHeaderCellMouseDown(e) : this.onCellMouseDown(e);
+ },
+
+ onMouseOverRow: function(e){
+ // summary:
+ // Event fired when mouse is over any row (data or header).
+ // e: Event
+ // Decorated event object contains reference to grid, cell, and rowIndex
+ if(!this.rows.isOver(e.rowIndex)){
+ this.rows.setOverRow(e.rowIndex);
+ e.rowIndex == -1 ? this.onHeaderMouseOver(e) : this.onRowMouseOver(e);
+ }
+ },
+ onMouseOutRow: function(e){
+ // summary:
+ // Event fired when mouse moves out of any row (data or header).
+ // e: Event
+ // Decorated event object contains reference to grid, cell, and rowIndex
+ if(this.rows.isOver(-1)){
+ this.onHeaderMouseOut(e);
+ }else if(!this.rows.isOver(-2)){
+ this.rows.setOverRow(-2);
+ this.onRowMouseOut(e);
+ }
+ },
+
+ onMouseDownRow: function(e){
+ // summary:
+ // Event fired when mouse is down inside grid row
+ // e: Event
+ // Decorated event object that contains reference to grid, cell, and rowIndex
+ if(e.rowIndex != -1)
+ this.onRowMouseDown(e);
+ },
+
+ // cell events
+ onCellMouseOver: function(e){
+ // summary:
+ // Event fired when mouse is over a cell.
+ // e: Event
+ // Decorated event object contains reference to grid, cell, and rowIndex
+ dojo.addClass(e.cellNode, this.cellOverClass);
+ },
+
+ onCellMouseOut: function(e){
+ // summary:
+ // Event fired when mouse moves out of a cell.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ dojo.removeClass(e.cellNode, this.cellOverClass);
+ },
+
+ onCellMouseDown: function(e){
+ // summary:
+ // Event fired when mouse is down in a header cell.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ },
+
+ onCellClick: function(e){
+ // summary:
+ // Event fired when a cell is clicked.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ this._click[0] = this._click[1];
+ this._click[1] = e;
+ if(!this.edit.isEditCell(e.rowIndex, e.cellIndex)){
+ this.focus.setFocusCell(e.cell, e.rowIndex);
+ }
+ this.onRowClick(e);
+ },
+
+ onCellDblClick: function(e){
+ // summary:
+ // Event fired when a cell is double-clicked.
+ // e: Event
+ // Decorated event object contains reference to grid, cell, and rowIndex
+ if(dojo.isIE){
+ this.edit.setEditCell(this._click[1].cell, this._click[1].rowIndex);
+ }else if(this._click[0].rowIndex != this._click[1].rowIndex){
+ this.edit.setEditCell(this._click[0].cell, this._click[0].rowIndex);
+ }else{
+ this.edit.setEditCell(e.cell, e.rowIndex);
+ }
+ this.onRowDblClick(e);
+ },
+
+ onCellContextMenu: function(e){
+ // summary:
+ // Event fired when a cell context menu is accessed via mouse right click.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ this.onRowContextMenu(e);
+ },
+
+ onCellFocus: function(inCell, inRowIndex){
+ // summary:
+ // Event fired when a cell receives focus.
+ // inCell: Object
+ // Cell object containing properties of the grid column.
+ // inRowIndex: Integer
+ // Index of the grid row
+ this.edit.cellFocus(inCell, inRowIndex);
+ },
+
+ // row events
+ onRowClick: function(e){
+ // summary:
+ // Event fired when a row is clicked.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ this.edit.rowClick(e);
+ this.selection.clickSelectEvent(e);
+ },
+
+ onRowDblClick: function(e){
+ // summary:
+ // Event fired when a row is double clicked.
+ // e: Event
+ // decorated event object which contains reference to grid, cell, and rowIndex
+ },
+
+ onRowMouseOver: function(e){
+ // summary:
+ // Event fired when mouse moves over a data row.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ },
+
+ onRowMouseOut: function(e){
+ // summary:
+ // Event fired when mouse moves out of a data row.
+ // e: Event
+ // Decorated event object contains reference to grid, cell, and rowIndex
+ },
+
+ onRowMouseDown: function(e){
+ // summary:
+ // Event fired when mouse is down in a row.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ },
+
+ onRowContextMenu: function(e){
+ // summary:
+ // Event fired when a row context menu is accessed via mouse right click.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ dojo.stopEvent(e);
+ },
+
+ // header events
+ onHeaderMouseOver: function(e){
+ // summary:
+ // Event fired when mouse moves over the grid header.
+ // e: Event
+ // Decorated event object contains reference to grid, cell, and rowIndex
+ },
+
+ onHeaderMouseOut: function(e){
+ // summary:
+ // Event fired when mouse moves out of the grid header.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ },
+
+ onHeaderCellMouseOver: function(e){
+ // summary:
+ // Event fired when mouse moves over a header cell.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ dojo.addClass(e.cellNode, this.cellOverClass);
+ },
+
+ onHeaderCellMouseOut: function(e){
+ // summary:
+ // Event fired when mouse moves out of a header cell.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ dojo.removeClass(e.cellNode, this.cellOverClass);
+ },
+
+ onHeaderCellMouseDown: function(e) {
+ // summary:
+ // Event fired when mouse is down in a header cell.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ },
+
+ onHeaderClick: function(e){
+ // summary:
+ // Event fired when the grid header is clicked.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ },
+
+ onHeaderCellClick: function(e){
+ // summary:
+ // Event fired when a header cell is clicked.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ this.setSortIndex(e.cell.index);
+ this.onHeaderClick(e);
+ },
+
+ onHeaderDblClick: function(e){
+ // summary:
+ // Event fired when the grid header is double clicked.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ },
+
+ onHeaderCellDblClick: function(e){
+ // summary:
+ // Event fired when a header cell is double clicked.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ this.onHeaderDblClick(e);
+ },
+
+ onHeaderCellContextMenu: function(e){
+ // summary:
+ // Event fired when a header cell context menu is accessed via mouse right click.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ this.onHeaderContextMenu(e);
+ },
+
+ onHeaderContextMenu: function(e){
+ // summary:
+ // Event fired when the grid header context menu is accessed via mouse right click.
+ // e: Event
+ // Decorated event object which contains reference to grid, cell, and rowIndex
+ dojo.stopEvent(e);
+ },
+
+ // editing
+ onStartEdit: function(inCell, inRowIndex){
+ // summary:
+ // Event fired when editing is started for a given grid cell
+ // inCell: Object
+ // Cell object containing properties of the grid column.
+ // inRowIndex: Integer
+ // Index of the grid row
+ },
+
+ onApplyCellEdit: function(inValue, inRowIndex, inFieldIndex){
+ // summary:
+ // Event fired when editing is applied for a given grid cell
+ // inValue: String
+ // Value from cell editor
+ // inRowIndex: Integer
+ // Index of the grid row
+ // inFieldIndex: Integer
+ // Index in the grid's data model
+ },
+
+ onCancelEdit: function(inRowIndex){
+ // summary:
+ // Event fired when editing is cancelled for a given grid cell
+ // inRowIndex: Integer
+ // Index of the grid row
+ },
+
+ onApplyEdit: function(inRowIndex){
+ // summary:
+ // Event fired when editing is applied for a given grid row
+ // inRowIndex: Integer
+ // Index of the grid row
+ },
+
+ onCanSelect: function(inRowIndex){
+ // summary:
+ // Event to determine if a grid row may be selected
+ // inRowIndex: Integer
+ // Index of the grid row
+ // returns: Boolean
+ // true if the row can be selected
+ return true;
+ },
+
+ onCanDeselect: function(inRowIndex){
+ // summary:
+ // Event to determine if a grid row may be deselected
+ // inRowIndex: Integer
+ // Index of the grid row
+ // returns: Boolean
+ // true if the row can be deselected
+ return true;
+ },
+
+ onSelected: function(inRowIndex){
+ // summary:
+ // Event fired when a grid row is selected
+ // inRowIndex: Integer
+ // Index of the grid row
+ this.updateRowStyles(inRowIndex);
+ },
+
+ onDeselected: function(inRowIndex){
+ // summary:
+ // Event fired when a grid row is deselected
+ // inRowIndex: Integer
+ // Index of the grid row
+ this.updateRowStyles(inRowIndex);
+ },
+
+ onSelectionChanged: function(){
+ }
+
+}
+
+}
diff --git a/includes/js/dojox/grid/_grid/rowbar.js b/includes/js/dojox/grid/_grid/rowbar.js
new file mode 100644
index 0000000..d5e34c0
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/rowbar.js
@@ -0,0 +1,53 @@
+if(!dojo._hasResource["dojox.grid._grid.rowbar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._grid.rowbar"] = true;
+dojo.provide("dojox.grid._grid.rowbar");
+dojo.require("dojox.grid._grid.view");
+
+dojo.declare('dojox.GridRowView', dojox.GridView, {
+ // summary:
+ // Custom grid view. If used in a grid structure, provides a small selectable region for grid rows.
+ defaultWidth: "3em",
+ noscroll: true,
+ padBorderWidth: 2,
+ buildRendering: function(){
+ this.inherited('buildRendering', arguments);
+ this.scrollboxNode.style.overflow = "hidden";
+ this.headerNode.style.visibility = "hidden";
+ },
+ getWidth: function(){
+ return this.viewWidth || this.defaultWidth;
+ },
+ buildRowContent: function(inRowIndex, inRowNode){
+ var w = this.contentNode.offsetWidth - this.padBorderWidth
+ inRowNode.innerHTML = '<table style="width:' + w + 'px;" role="wairole:presentation"><tr><td class="dojoxGrid-rowbar-inner"></td></tr></table>';
+ },
+ renderHeader: function(){
+ },
+ resize: function(){
+ this.adaptHeight();
+ },
+ adaptWidth: function(){
+ },
+ // styling
+ doStyleRowNode: function(inRowIndex, inRowNode){
+ var n = [ "dojoxGrid-rowbar" ];
+ if(this.grid.rows.isOver(inRowIndex)){
+ n.push("dojoxGrid-rowbar-over");
+ }
+ if(this.grid.selection.isSelected(inRowIndex)){
+ n.push("dojoxGrid-rowbar-selected");
+ }
+ inRowNode.className = n.join(" ");
+ },
+ // event handlers
+ domouseover: function(e){
+ this.grid.onMouseOverRow(e);
+ },
+ domouseout: function(e){
+ if(!this.isIntraRowEvent(e)){
+ this.grid.onMouseOutRow(e);
+ }
+ }
+});
+
+}
diff --git a/includes/js/dojox/grid/_grid/rows.js b/includes/js/dojox/grid/_grid/rows.js
new file mode 100644
index 0000000..37ecbcb
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/rows.js
@@ -0,0 +1,66 @@
+if(!dojo._hasResource["dojox.grid._grid.rows"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._grid.rows"] = true;
+dojo.provide("dojox.grid._grid.rows");
+
+dojo.declare("dojox.grid.rows", null, {
+ // Stores information about grid rows. Owned by grid and used internally.
+ constructor: function(inGrid){
+ this.grid = inGrid;
+ },
+ linesToEms: 2,
+ defaultRowHeight: 1, // lines
+ overRow: -2,
+ // metrics
+ getHeight: function(inRowIndex){
+ return '';
+ },
+ getDefaultHeightPx: function(){
+ // summmary:
+ // retrieves the default row height
+ // returns: int, default row height
+ return 32;
+ //return Math.round(this.defaultRowHeight * this.linesToEms * this.grid.contentPixelToEmRatio);
+ },
+ // styles
+ prepareStylingRow: function(inRowIndex, inRowNode){
+ return {
+ index: inRowIndex,
+ node: inRowNode,
+ odd: Boolean(inRowIndex&1),
+ selected: this.grid.selection.isSelected(inRowIndex),
+ over: this.isOver(inRowIndex),
+ customStyles: "",
+ customClasses: "dojoxGrid-row"
+ }
+ },
+ styleRowNode: function(inRowIndex, inRowNode){
+ var row = this.prepareStylingRow(inRowIndex, inRowNode);
+ this.grid.onStyleRow(row);
+ this.applyStyles(row);
+ },
+ applyStyles: function(inRow){
+ with(inRow){
+ node.className = customClasses;
+ var h = node.style.height;
+ dojox.grid.setStyleText(node, customStyles + ';' + (node._style||''));
+ node.style.height = h;
+ }
+ },
+ updateStyles: function(inRowIndex){
+ this.grid.updateRowStyles(inRowIndex);
+ },
+ // states and events
+ setOverRow: function(inRowIndex){
+ var last = this.overRow;
+ this.overRow = inRowIndex;
+ if((last!=this.overRow)&&(last >=0)){
+ this.updateStyles(last);
+ }
+ this.updateStyles(this.overRow);
+ },
+ isOver: function(inRowIndex){
+ return (this.overRow == inRowIndex);
+ }
+});
+
+}
diff --git a/includes/js/dojox/grid/_grid/scroller.js b/includes/js/dojox/grid/_grid/scroller.js
new file mode 100644
index 0000000..d331367
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/scroller.js
@@ -0,0 +1,489 @@
+if(!dojo._hasResource['dojox.grid._grid.scroller']){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource['dojox.grid._grid.scroller'] = true;
+dojo.provide('dojox.grid._grid.scroller');
+
+dojo.declare('dojox.grid.scroller.base', null, {
+ // summary:
+ // virtual scrollbox, abstract class
+ // Content must in /rows/
+ // Rows are managed in contiguous sets called /pages/
+ // There are a fixed # of rows per page
+ // The minimum rendered unit is a page
+ constructor: function(){
+ this.pageHeights = [];
+ this.stack = [];
+ },
+ // specified
+ rowCount: 0, // total number of rows to manage
+ defaultRowHeight: 10, // default height of a row
+ keepRows: 100, // maximum number of rows that should exist at one time
+ contentNode: null, // node to contain pages
+ scrollboxNode: null, // node that controls scrolling
+ // calculated
+ defaultPageHeight: 0, // default height of a page
+ keepPages: 10, // maximum number of pages that should exists at one time
+ pageCount: 0,
+ windowHeight: 0,
+ firstVisibleRow: 0,
+ lastVisibleRow: 0,
+ // private
+ page: 0,
+ pageTop: 0,
+ // init
+ init: function(inRowCount, inKeepRows, inRowsPerPage){
+ switch(arguments.length){
+ case 3: this.rowsPerPage = inRowsPerPage;
+ case 2: this.keepRows = inKeepRows;
+ case 1: this.rowCount = inRowCount;
+ }
+ this.defaultPageHeight = this.defaultRowHeight * this.rowsPerPage;
+ //this.defaultPageHeight = this.defaultRowHeight * Math.min(this.rowsPerPage, this.rowCount);
+ this.pageCount = Math.ceil(this.rowCount / this.rowsPerPage);
+ this.setKeepInfo(this.keepRows);
+ this.invalidate();
+ if(this.scrollboxNode){
+ this.scrollboxNode.scrollTop = 0;
+ this.scroll(0);
+ this.scrollboxNode.onscroll = dojo.hitch(this, 'onscroll');
+ }
+ },
+ setKeepInfo: function(inKeepRows){
+ this.keepRows = inKeepRows;
+ this.keepPages = !this.keepRows ? this.keepRows : Math.max(Math.ceil(this.keepRows / this.rowsPerPage), 2);
+ },
+ // updating
+ invalidate: function(){
+ this.invalidateNodes();
+ this.pageHeights = [];
+ this.height = (this.pageCount ? (this.pageCount - 1)* this.defaultPageHeight + this.calcLastPageHeight() : 0);
+ this.resize();
+ },
+ updateRowCount: function(inRowCount){
+ this.invalidateNodes();
+ this.rowCount = inRowCount;
+ // update page count, adjust document height
+ oldPageCount = this.pageCount;
+ this.pageCount = Math.ceil(this.rowCount / this.rowsPerPage);
+ if(this.pageCount < oldPageCount){
+ for(var i=oldPageCount-1; i>=this.pageCount; i--){
+ this.height -= this.getPageHeight(i);
+ delete this.pageHeights[i]
+ }
+ }else if(this.pageCount > oldPageCount){
+ this.height += this.defaultPageHeight * (this.pageCount - oldPageCount - 1) + this.calcLastPageHeight();
+ }
+ this.resize();
+ },
+ // abstract interface
+ pageExists: function(inPageIndex){
+ },
+ measurePage: function(inPageIndex){
+ },
+ positionPage: function(inPageIndex, inPos){
+ },
+ repositionPages: function(inPageIndex){
+ },
+ installPage: function(inPageIndex){
+ },
+ preparePage: function(inPageIndex, inPos, inReuseNode){
+ },
+ renderPage: function(inPageIndex){
+ },
+ removePage: function(inPageIndex){
+ },
+ pacify: function(inShouldPacify){
+ },
+ // pacification
+ pacifying: false,
+ pacifyTicks: 200,
+ setPacifying: function(inPacifying){
+ if(this.pacifying != inPacifying){
+ this.pacifying = inPacifying;
+ this.pacify(this.pacifying);
+ }
+ },
+ startPacify: function(){
+ this.startPacifyTicks = new Date().getTime();
+ },
+ doPacify: function(){
+ var result = (new Date().getTime() - this.startPacifyTicks) > this.pacifyTicks;
+ this.setPacifying(true);
+ this.startPacify();
+ return result;
+ },
+ endPacify: function(){
+ this.setPacifying(false);
+ },
+ // default sizing implementation
+ resize: function(){
+ if(this.scrollboxNode){
+ this.windowHeight = this.scrollboxNode.clientHeight;
+ }
+ dojox.grid.setStyleHeightPx(this.contentNode, this.height);
+ },
+ calcLastPageHeight: function(){
+ if(!this.pageCount){
+ return 0;
+ }
+ var lastPage = this.pageCount - 1;
+ var lastPageHeight = ((this.rowCount % this.rowsPerPage)||(this.rowsPerPage)) * this.defaultRowHeight;
+ this.pageHeights[lastPage] = lastPageHeight;
+ return lastPageHeight;
+ },
+ updateContentHeight: function(inDh){
+ this.height += inDh;
+ this.resize();
+ },
+ updatePageHeight: function(inPageIndex){
+ if(this.pageExists(inPageIndex)){
+ var oh = this.getPageHeight(inPageIndex);
+ var h = (this.measurePage(inPageIndex))||(oh);
+ this.pageHeights[inPageIndex] = h;
+ if((h)&&(oh != h)){
+ this.updateContentHeight(h - oh)
+ this.repositionPages(inPageIndex);
+ }
+ }
+ },
+ rowHeightChanged: function(inRowIndex){
+ this.updatePageHeight(Math.floor(inRowIndex / this.rowsPerPage));
+ },
+ // scroller core
+ invalidateNodes: function(){
+ while(this.stack.length){
+ this.destroyPage(this.popPage());
+ }
+ },
+ createPageNode: function(){
+ var p = document.createElement('div');
+ p.style.position = 'absolute';
+ //p.style.width = '100%';
+ p.style[dojo._isBodyLtr() ? "left" : "right"] = '0';
+ return p;
+ },
+ getPageHeight: function(inPageIndex){
+ var ph = this.pageHeights[inPageIndex];
+ return (ph !== undefined ? ph : this.defaultPageHeight);
+ },
+ // FIXME: this is not a stack, it's a FIFO list
+ pushPage: function(inPageIndex){
+ return this.stack.push(inPageIndex);
+ },
+ popPage: function(){
+ return this.stack.shift();
+ },
+ findPage: function(inTop){
+ var i = 0, h = 0;
+ for(var ph = 0; i<this.pageCount; i++, h += ph){
+ ph = this.getPageHeight(i);
+ if(h + ph >= inTop){
+ break;
+ }
+ }
+ this.page = i;
+ this.pageTop = h;
+ },
+ buildPage: function(inPageIndex, inReuseNode, inPos){
+ this.preparePage(inPageIndex, inReuseNode);
+ this.positionPage(inPageIndex, inPos);
+ // order of operations is key below
+ this.installPage(inPageIndex);
+ this.renderPage(inPageIndex);
+ // order of operations is key above
+ this.pushPage(inPageIndex);
+ },
+ needPage: function(inPageIndex, inPos){
+ var h = this.getPageHeight(inPageIndex), oh = h;
+ if(!this.pageExists(inPageIndex)){
+ this.buildPage(inPageIndex, this.keepPages&&(this.stack.length >= this.keepPages), inPos);
+ h = this.measurePage(inPageIndex) || h;
+ this.pageHeights[inPageIndex] = h;
+ if(h && (oh != h)){
+ this.updateContentHeight(h - oh)
+ }
+ }else{
+ this.positionPage(inPageIndex, inPos);
+ }
+ return h;
+ },
+ onscroll: function(){
+ this.scroll(this.scrollboxNode.scrollTop);
+ },
+ scroll: function(inTop){
+ this.startPacify();
+ this.findPage(inTop);
+ var h = this.height;
+ var b = this.getScrollBottom(inTop);
+ for(var p=this.page, y=this.pageTop; (p<this.pageCount)&&((b<0)||(y<b)); p++){
+ y += this.needPage(p, y);
+ }
+ this.firstVisibleRow = this.getFirstVisibleRow(this.page, this.pageTop, inTop);
+ this.lastVisibleRow = this.getLastVisibleRow(p - 1, y, b);
+ // indicates some page size has been updated
+ if(h != this.height){
+ this.repositionPages(p-1);
+ }
+ this.endPacify();
+ },
+ getScrollBottom: function(inTop){
+ return (this.windowHeight >= 0 ? inTop + this.windowHeight : -1);
+ },
+ // events
+ processNodeEvent: function(e, inNode){
+ var t = e.target;
+ while(t && (t != inNode) && t.parentNode && (t.parentNode.parentNode != inNode)){
+ t = t.parentNode;
+ }
+ if(!t || !t.parentNode || (t.parentNode.parentNode != inNode)){
+ return false;
+ }
+ var page = t.parentNode;
+ e.topRowIndex = page.pageIndex * this.rowsPerPage;
+ e.rowIndex = e.topRowIndex + dojox.grid.indexInParent(t);
+ e.rowTarget = t;
+ return true;
+ },
+ processEvent: function(e){
+ return this.processNodeEvent(e, this.contentNode);
+ },
+ dummy: 0
+});
+
+dojo.declare('dojox.grid.scroller', dojox.grid.scroller.base, {
+ // summary:
+ // virtual scroller class, makes no assumption about shape of items being scrolled
+ constructor: function(){
+ this.pageNodes = [];
+ },
+ // virtual rendering interface
+ renderRow: function(inRowIndex, inPageNode){
+ },
+ removeRow: function(inRowIndex){
+ },
+ // page node operations
+ getDefaultNodes: function(){
+ return this.pageNodes;
+ },
+ getDefaultPageNode: function(inPageIndex){
+ return this.getDefaultNodes()[inPageIndex];
+ },
+ positionPageNode: function(inNode, inPos){
+ inNode.style.top = inPos + 'px';
+ },
+ getPageNodePosition: function(inNode){
+ return inNode.offsetTop;
+ },
+ repositionPageNodes: function(inPageIndex, inNodes){
+ var last = 0;
+ for(var i=0; i<this.stack.length; i++){
+ last = Math.max(this.stack[i], last);
+ }
+ //
+ var n = inNodes[inPageIndex];
+ var y = (n ? this.getPageNodePosition(n) + this.getPageHeight(inPageIndex) : 0);
+ //console.log('detected height change, repositioning from #%d (%d) @ %d ', inPageIndex + 1, last, y, this.pageHeights[0]);
+ //
+ for(var p=inPageIndex+1; p<=last; p++){
+ n = inNodes[p];
+ if(n){
+ //console.log('#%d @ %d', inPageIndex, y, this.getPageNodePosition(n));
+ if(this.getPageNodePosition(n) == y){
+ return;
+ }
+ //console.log('placing page %d at %d', p, y);
+ this.positionPage(p, y);
+ }
+ y += this.getPageHeight(p);
+ }
+ },
+ invalidatePageNode: function(inPageIndex, inNodes){
+ var p = inNodes[inPageIndex];
+ if(p){
+ delete inNodes[inPageIndex];
+ this.removePage(inPageIndex, p);
+ dojox.grid.cleanNode(p);
+ p.innerHTML = '';
+ }
+ return p;
+ },
+ preparePageNode: function(inPageIndex, inReusePageIndex, inNodes){
+ var p = (inReusePageIndex === null ? this.createPageNode() : this.invalidatePageNode(inReusePageIndex, inNodes));
+ p.pageIndex = inPageIndex;
+ p.id = (this._pageIdPrefix || "") + 'page-' + inPageIndex;
+ inNodes[inPageIndex] = p;
+ },
+ // implementation for page manager
+ pageExists: function(inPageIndex){
+ return Boolean(this.getDefaultPageNode(inPageIndex));
+ },
+ measurePage: function(inPageIndex){
+ return this.getDefaultPageNode(inPageIndex).offsetHeight;
+ },
+ positionPage: function(inPageIndex, inPos){
+ this.positionPageNode(this.getDefaultPageNode(inPageIndex), inPos);
+ },
+ repositionPages: function(inPageIndex){
+ this.repositionPageNodes(inPageIndex, this.getDefaultNodes());
+ },
+ preparePage: function(inPageIndex, inReuseNode){
+ this.preparePageNode(inPageIndex, (inReuseNode ? this.popPage() : null), this.getDefaultNodes());
+ },
+ installPage: function(inPageIndex){
+ this.contentNode.appendChild(this.getDefaultPageNode(inPageIndex));
+ },
+ destroyPage: function(inPageIndex){
+ var p = this.invalidatePageNode(inPageIndex, this.getDefaultNodes());
+ dojox.grid.removeNode(p);
+ },
+ // rendering implementation
+ renderPage: function(inPageIndex){
+ var node = this.pageNodes[inPageIndex];
+ for(var i=0, j=inPageIndex*this.rowsPerPage; (i<this.rowsPerPage)&&(j<this.rowCount); i++, j++){
+ this.renderRow(j, node);
+ }
+ },
+ removePage: function(inPageIndex){
+ for(var i=0, j=inPageIndex*this.rowsPerPage; i<this.rowsPerPage; i++, j++){
+ this.removeRow(j);
+ }
+ },
+ // scroll control
+ getPageRow: function(inPage){
+ return inPage * this.rowsPerPage;
+ },
+ getLastPageRow: function(inPage){
+ return Math.min(this.rowCount, this.getPageRow(inPage + 1)) - 1;
+ },
+ getFirstVisibleRowNodes: function(inPage, inPageTop, inScrollTop, inNodes){
+ var row = this.getPageRow(inPage);
+ var rows = dojox.grid.divkids(inNodes[inPage]);
+ for(var i=0,l=rows.length; i<l && inPageTop<inScrollTop; i++, row++){
+ inPageTop += rows[i].offsetHeight;
+ }
+ return (row ? row - 1 : row);
+ },
+ getFirstVisibleRow: function(inPage, inPageTop, inScrollTop){
+ if(!this.pageExists(inPage)){
+ return 0;
+ }
+ return this.getFirstVisibleRowNodes(inPage, inPageTop, inScrollTop, this.getDefaultNodes());
+ },
+ getLastVisibleRowNodes: function(inPage, inBottom, inScrollBottom, inNodes){
+ var row = this.getLastPageRow(inPage);
+ var rows = dojox.grid.divkids(inNodes[inPage]);
+ for(var i=rows.length-1; i>=0 && inBottom>inScrollBottom; i--, row--){
+ inBottom -= rows[i].offsetHeight;
+ }
+ return row + 1;
+ },
+ getLastVisibleRow: function(inPage, inBottom, inScrollBottom){
+ if(!this.pageExists(inPage)){
+ return 0;
+ }
+ return this.getLastVisibleRowNodes(inPage, inBottom, inScrollBottom, this.getDefaultNodes());
+ },
+ findTopRowForNodes: function(inScrollTop, inNodes){
+ var rows = dojox.grid.divkids(inNodes[this.page]);
+ for(var i=0,l=rows.length,t=this.pageTop,h; i<l; i++){
+ h = rows[i].offsetHeight;
+ t += h;
+ if(t >= inScrollTop){
+ this.offset = h - (t - inScrollTop);
+ return i + this.page * this.rowsPerPage;
+ }
+ }
+ return -1;
+ },
+ findScrollTopForNodes: function(inRow, inNodes){
+ var rowPage = Math.floor(inRow / this.rowsPerPage);
+ var t = 0;
+ for(var i=0; i<rowPage; i++){
+ t += this.getPageHeight(i);
+ }
+ this.pageTop = t;
+ this.needPage(rowPage, this.pageTop);
+ var rows = dojox.grid.divkids(inNodes[rowPage]);
+ var r = inRow - this.rowsPerPage * rowPage;
+ for(var i=0,l=rows.length; i<l && i<r; i++){
+ t += rows[i].offsetHeight;
+ }
+ return t;
+ },
+ findTopRow: function(inScrollTop){
+ return this.findTopRowForNodes(inScrollTop, this.getDefaultNodes());
+ },
+ findScrollTop: function(inRow){
+ return this.findScrollTopForNodes(inRow, this.getDefaultNodes());
+ },
+ dummy: 0
+});
+
+dojo.declare('dojox.grid.scroller.columns', dojox.grid.scroller, {
+ // summary:
+ // Virtual scroller class that scrolls list of columns. Owned by grid and used internally
+ // for virtual scrolling.
+ constructor: function(inContentNodes){
+ this.setContentNodes(inContentNodes);
+ },
+ // nodes
+ setContentNodes: function(inNodes){
+ this.contentNodes = inNodes;
+ this.colCount = (this.contentNodes ? this.contentNodes.length : 0);
+ this.pageNodes = [];
+ for(var i=0; i<this.colCount; i++){
+ this.pageNodes[i] = [];
+ }
+ },
+ getDefaultNodes: function(){
+ return this.pageNodes[0] || [];
+ },
+ scroll: function(inTop) {
+ if(this.colCount){
+ dojox.grid.scroller.prototype.scroll.call(this, inTop);
+ }
+ },
+ // resize
+ resize: function(){
+ if(this.scrollboxNode){
+ this.windowHeight = this.scrollboxNode.clientHeight;
+ }
+ for(var i=0; i<this.colCount; i++){
+ dojox.grid.setStyleHeightPx(this.contentNodes[i], this.height);
+ }
+ },
+ // implementation for page manager
+ positionPage: function(inPageIndex, inPos){
+ for(var i=0; i<this.colCount; i++){
+ this.positionPageNode(this.pageNodes[i][inPageIndex], inPos);
+ }
+ },
+ preparePage: function(inPageIndex, inReuseNode){
+ var p = (inReuseNode ? this.popPage() : null);
+ for(var i=0; i<this.colCount; i++){
+ this.preparePageNode(inPageIndex, p, this.pageNodes[i]);
+ }
+ },
+ installPage: function(inPageIndex){
+ for(var i=0; i<this.colCount; i++){
+ this.contentNodes[i].appendChild(this.pageNodes[i][inPageIndex]);
+ }
+ },
+ destroyPage: function(inPageIndex){
+ for(var i=0; i<this.colCount; i++){
+ dojox.grid.removeNode(this.invalidatePageNode(inPageIndex, this.pageNodes[i]));
+ }
+ },
+ // rendering implementation
+ renderPage: function(inPageIndex){
+ var nodes = [];
+ for(var i=0; i<this.colCount; i++){
+ nodes[i] = this.pageNodes[i][inPageIndex];
+ }
+ //this.renderRows(inPageIndex*this.rowsPerPage, this.rowsPerPage, nodes);
+ for(var i=0, j=inPageIndex*this.rowsPerPage; (i<this.rowsPerPage)&&(j<this.rowCount); i++, j++){
+ this.renderRow(j, nodes);
+ }
+ }
+});
+
+}
diff --git a/includes/js/dojox/grid/_grid/selection.js b/includes/js/dojox/grid/_grid/selection.js
new file mode 100644
index 0000000..75229c0
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/selection.js
@@ -0,0 +1,215 @@
+if(!dojo._hasResource['dojox.grid._grid.selection']){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource['dojox.grid._grid.selection'] = true;
+dojo.provide('dojox.grid._grid.selection');
+
+dojo.declare("dojox.grid.selection",
+ null,
+ {
+ // summary:
+ // Manages row selection for grid. Owned by grid and used internally
+ // for selection. Override to implement custom selection.
+
+ constructor: function(inGrid){
+ this.grid = inGrid;
+ this.selected = [];
+ },
+
+ multiSelect: true,
+ selected: null,
+ updating: 0,
+ selectedIndex: -1,
+
+ onCanSelect: function(inIndex){
+ return this.grid.onCanSelect(inIndex);
+ },
+
+ onCanDeselect: function(inIndex){
+ return this.grid.onCanDeselect(inIndex);
+ },
+
+ onSelected: function(inIndex){
+ return this.grid.onSelected(inIndex);
+ },
+
+ onDeselected: function(inIndex){
+ return this.grid.onDeselected(inIndex);
+ },
+
+ //onSetSelected: function(inIndex, inSelect) { };
+ onChanging: function(){
+ },
+
+ onChanged: function(){
+ return this.grid.onSelectionChanged();
+ },
+
+ isSelected: function(inIndex){
+ return this.selected[inIndex];
+ },
+
+ getFirstSelected: function(){
+ for(var i=0, l=this.selected.length; i<l; i++){
+ if(this.selected[i]){
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ getNextSelected: function(inPrev){
+ for(var i=inPrev+1, l=this.selected.length; i<l; i++){
+ if(this.selected[i]){
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ getSelected: function(){
+ var result = [];
+ for(var i=0, l=this.selected.length; i<l; i++){
+ if(this.selected[i]){
+ result.push(i);
+ }
+ }
+ return result;
+ },
+
+ getSelectedCount: function(){
+ var c = 0;
+ for(var i=0; i<this.selected.length; i++){
+ if(this.selected[i]){
+ c++;
+ }
+ }
+ return c;
+ },
+
+ beginUpdate: function(){
+ if(this.updating == 0){
+ this.onChanging();
+ }
+ this.updating++;
+ },
+
+ endUpdate: function(){
+ this.updating--;
+ if(this.updating == 0){
+ this.onChanged();
+ }
+ },
+
+ select: function(inIndex){
+ this.unselectAll(inIndex);
+ this.addToSelection(inIndex);
+ },
+
+ addToSelection: function(inIndex){
+ inIndex = Number(inIndex);
+ if(this.selected[inIndex]){
+ this.selectedIndex = inIndex;
+ }else{
+ if(this.onCanSelect(inIndex) !== false){
+ this.selectedIndex = inIndex;
+ this.beginUpdate();
+ this.selected[inIndex] = true;
+ this.grid.onSelected(inIndex);
+ //this.onSelected(inIndex);
+ //this.onSetSelected(inIndex, true);
+ this.endUpdate();
+ }
+ }
+ },
+
+ deselect: function(inIndex){
+ inIndex = Number(inIndex);
+ if(this.selectedIndex == inIndex){
+ this.selectedIndex = -1;
+ }
+ if(this.selected[inIndex]){
+ if(this.onCanDeselect(inIndex) === false){
+ return;
+ }
+ this.beginUpdate();
+ delete this.selected[inIndex];
+ this.grid.onDeselected(inIndex);
+ //this.onDeselected(inIndex);
+ //this.onSetSelected(inIndex, false);
+ this.endUpdate();
+ }
+ },
+
+ setSelected: function(inIndex, inSelect){
+ this[(inSelect ? 'addToSelection' : 'deselect')](inIndex);
+ },
+
+ toggleSelect: function(inIndex){
+ this.setSelected(inIndex, !this.selected[inIndex])
+ },
+
+ insert: function(inIndex){
+ this.selected.splice(inIndex, 0, false);
+ if(this.selectedIndex >= inIndex){
+ this.selectedIndex++;
+ }
+ },
+
+ remove: function(inIndex){
+ this.selected.splice(inIndex, 1);
+ if(this.selectedIndex >= inIndex){
+ this.selectedIndex--;
+ }
+ },
+
+ unselectAll: function(inExcept){
+ for(var i in this.selected){
+ if((i!=inExcept)&&(this.selected[i]===true)){
+ this.deselect(i);
+ }
+ }
+ },
+
+ shiftSelect: function(inFrom, inTo){
+ var s = (inFrom >= 0 ? inFrom : inTo), e = inTo;
+ if(s > e){
+ e = s;
+ s = inTo;
+ }
+ for(var i=s; i<=e; i++){
+ this.addToSelection(i);
+ }
+ },
+
+ clickSelect: function(inIndex, inCtrlKey, inShiftKey){
+ this.beginUpdate();
+ if(!this.multiSelect){
+ this.select(inIndex);
+ }else{
+ var lastSelected = this.selectedIndex;
+ if(!inCtrlKey){
+ this.unselectAll(inIndex);
+ }
+ if(inShiftKey){
+ this.shiftSelect(lastSelected, inIndex);
+ }else if(inCtrlKey){
+ this.toggleSelect(inIndex);
+ }else{
+ this.addToSelection(inIndex)
+ }
+ }
+ this.endUpdate();
+ },
+
+ clickSelectEvent: function(e){
+ this.clickSelect(e.rowIndex, e.ctrlKey, e.shiftKey);
+ },
+
+ clear: function(){
+ this.beginUpdate();
+ this.unselectAll();
+ this.endUpdate();
+ }
+
+});
+
+}
diff --git a/includes/js/dojox/grid/_grid/soriaGrid.css b/includes/js/dojox/grid/_grid/soriaGrid.css
new file mode 100644
index 0000000..f244030
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/soriaGrid.css
@@ -0,0 +1,212 @@
+.soria .dojoxGrid {
+ position: relative;
+ background-color: #e9e9e9;
+ font-size: 0.85em;
+ -moz-outline-style: none;
+ outline: none;
+ overflow: hidden;
+ height: 0;
+}
+.soria .dojoxGrid table {
+ padding: 0;
+}
+.soria .dojoxGrid td {
+ -moz-outline: none;
+}
+.soria .dojoxGrid-master-header {
+ position: relative;
+}
+.soria .dojoxGrid-master-view {
+ position: relative;
+}
+.soria .dojoxGrid-view {
+ position: absolute;
+ overflow: hidden;
+}
+.soria .dojoxGrid-header {
+ position: absolute;
+ overflow: hidden;
+}
+.soria .dojoxGrid-header {
+ background-color: #e9e9e9;
+}
+.soria .dojoxGrid-header table {
+ text-align: center;
+}
+.soria .dojoxGrid-header .dojoxGrid-cell-content {
+ text-align: center;
+}
+.soria .dojoxGrid-header .dojoxGrid-cell {
+ border: 1px solid transparent;
+
+ border-color: white #ACA899 #919191 white;
+ background: url(../../../dijit/themes/soria/images/titleBar.png) #e9e9e9 repeat-x top;
+ padding-bottom: 2px;
+ color: #000 !important;
+}
+.soria .dojoxGrid-header .dojoxGrid-cell-over {
+ background: url(../../../dijit/themes/soria/images/titleBarActive.png) #e9e9e9 repeat-x top;
+}
+.soria .dojoxGrid-sort-down {
+ background: url(images/grid_sort_down.gif) right no-repeat;
+ padding-left: 0px;
+ margin-left: 0px;
+}
+.soria .dojoxGrid-sort-up {
+ background: url(images/grid_sort_up.gif) right no-repeat;
+ padding-left: 0px;
+ margin-left: 0px;
+}
+.soria .gridArrowButtonChar {
+ display:none !important;
+}
+.dijit_a11y .gridArrowButtonChar {
+ display:inline !important;
+}
+.soria .dojoxGrid-scrollbox {
+ position: relative;
+ overflow: scroll;
+ background-color: #fefefe;
+ width: 100%;
+}
+.soria .dojoxGrid-content {
+ position: relative;
+ overflow: hidden;
+ -moz-outline-style: none;
+ outline: none;
+}
+.soria .dojoxGrid-rowbar {
+ border: none;
+
+ background: url(images/titleBar.png) #e9e9e9 repeat-y right;
+ border-right: 1px solid #cccccc;
+ padding: 0px;
+}
+.soria .dojoxGrid-rowbar-inner {
+ border: none;
+ border-bottom: 1px solid #cccccc;
+}
+.soria .dojoxGrid-rowbar-over {
+ background: url(images/titleBarActive.png) #e9e9e9 repeat-y right;
+}
+.soria .dojoxGrid-rowbar-selected {
+ background-color: #D9E8F9;
+ background-image: none;
+ background: url(../../../dijit/themes/soria/images/titleBar.png) #dddddd repeat-x top;
+ border-right: 1px solid #cccccc;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+.soria .dojoxGrid-row {
+ position: relative;
+ width: 9000em;
+}
+.soria .dojoxGrid-row {
+ border: none;
+ border-left: none;
+ border-right: none;
+ background-color: white;
+ border-top: none;
+}
+.soria .dojoxGrid-row-over {
+ border-top-color: #cccccc;
+ border-bottom-color: #cccccc;
+}
+.soria .dojoxGrid-row-over .dojoxGrid-cell {
+ background-color: #60a1ea;
+ color:#fff;
+}
+.soria .dojoxGrid-row-odd {
+ background-color: #f2f5f9;
+
+}
+.soria .dojoxGrid-row-selected {
+ background-color: #aec7e3;
+}
+.soria .dojoxGrid-row-table {
+ table-layout: fixed;
+ width: 0;
+ border-collapse: collapse;
+}
+.soria .dojoxGrid-invisible {
+ visibility: hidden;
+}
+.soria .Xdojo-ie .dojoxGrid-invisible {
+ display: none;
+}
+.soria .dojoxGrid-invisible td, .dojoxGrid-header .dojoxGrid-invisible td {
+ border-top-width: 0;
+ border-bottom-width: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ height: 0;
+ overflow: hidden;
+}
+.soria .dojoxGrid-cell {
+ border: 1px dotted #D5CDB5;
+ padding: 3px 3px 3px 3px;
+ text-align: left;
+ overflow: hidden;
+}
+.dj_ie6 .soria .dojoxGrid-cell {
+ border: 1px solid white;
+ border-right: 1px solid #D5CDB5;
+}
+.soria .dojoxGrid-cell-focus {
+ border: 1px dotted #a6a6a6;
+}
+.soria .dojoxGrid-cell-over {
+ border: 1px dotted #a6a6a6;
+}
+.soria .dojoxGrid-cell-focus.dojoxGrid-cell-over {
+ border: 1px dotted #595959;
+}
+.soria .dojoxGrid-cell-clip {
+ width: 100%;
+ overflow: hidden;
+ white-space:nowrap;
+ text-overflow: ellipsis;
+}
+.soria .dojoxGrid-row-editing td {
+
+ background-color: #60a1ea;
+
+}
+.soria .dojoxGrid-row-inserting td {
+ background-color: #F4FFF4;
+}
+.soria .dojoxGrid-row-inflight td {
+ background-color: #F2F7B7;
+}
+.soria .dojoxGrid-row-error td {
+ background-color: #F8B8B6;
+}
+.soria .dojoxGrid-input,
+.soria .dojoxGrid-select,
+.soria .dojoxGrid-textarea {
+ margin: 0;
+ padding: 0px;
+ border-style: none;
+ width: 100%;
+ font-size: 100%;
+ font-family: inherit;
+}
+.dojoxGrid-hidden-focus {
+ position: absolute;
+ left: -1000px;
+ top: -1000px;
+ height: 0px, width: 0px;
+}
+.dijit_a11y .dojoxGrid-rowbar-selected {
+ border-top: 1px solid white;
+ border-bottom: 1px dashed black;
+ border-top: 0;
+ background: none;
+}
+.dijit_a11y .dojoxGrid-rowbar-selected .dojoxGrid-rowbar-inner {
+ border: 0;
+ border-top: 1px solid white;
+}
+.dijit_a11y .dojoxGrid-row-selected {
+ border-bottom: 1px dashed black;
+}
diff --git a/includes/js/dojox/grid/_grid/soriaGrid.css.commented.css b/includes/js/dojox/grid/_grid/soriaGrid.css.commented.css
new file mode 100644
index 0000000..06263ad
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/soriaGrid.css.commented.css
@@ -0,0 +1,276 @@
+.soria .dojoxGrid {
+ position: relative;
+ background-color: #e9e9e9;
+ font-size: 0.85em; /* inherit font-family from dojo.css */
+ -moz-outline-style: none;
+ outline: none;
+ overflow: hidden;
+ height: 0;
+}
+
+.soria .dojoxGrid table {
+ padding: 0;
+}
+
+.soria .dojoxGrid td {
+ -moz-outline: none;
+}
+
+/* master header */
+
+.soria .dojoxGrid-master-header {
+ position: relative;
+}
+
+/* master view */
+
+.soria .dojoxGrid-master-view {
+ position: relative;
+}
+
+/* views */
+
+.soria .dojoxGrid-view {
+ position: absolute;
+ overflow: hidden;
+}
+
+/* header */
+
+.soria .dojoxGrid-header {
+ position: absolute;
+ overflow: hidden;
+}
+
+.soria .dojoxGrid-header {
+ background-color: #e9e9e9;
+}
+
+.soria .dojoxGrid-header table {
+ text-align: center;
+}
+
+.soria .dojoxGrid-header .dojoxGrid-cell-content {
+ text-align: center;
+}
+
+.soria .dojoxGrid-header .dojoxGrid-cell {
+ border: 1px solid transparent;
+ /* border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB; */
+ border-color: white #ACA899 #919191 white;
+ background: url(../../../dijit/themes/soria/images/titleBar.png) #e9e9e9 repeat-x top;
+ padding-bottom: 2px;
+ color: #000 !important;
+}
+
+.soria .dojoxGrid-header .dojoxGrid-cell-over {
+ background: url(../../../dijit/themes/soria/images/titleBarActive.png) #e9e9e9 repeat-x top;
+}
+
+.soria .dojoxGrid-sort-down {
+ background: url(images/grid_sort_down.gif) right no-repeat;
+ padding-left: 0px;
+ margin-left: 0px;
+}
+
+.soria .dojoxGrid-sort-up {
+ background: url(images/grid_sort_up.gif) right no-repeat;
+ padding-left: 0px;
+ margin-left: 0px;
+}
+
+.soria .gridArrowButtonChar {
+ display:none !important;
+}
+.dijit_a11y .gridArrowButtonChar {
+ display:inline !important;
+}
+
+/* content */
+
+.soria .dojoxGrid-scrollbox {
+ position: relative;
+ overflow: scroll;
+ background-color: #fefefe;
+ width: 100%;
+}
+
+.soria .dojoxGrid-content {
+ position: relative;
+ overflow: hidden;
+ -moz-outline-style: none;
+ outline: none;
+}
+
+/* rowbar */
+
+.soria .dojoxGrid-rowbar {
+ border: none;
+ /*
+ border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
+ */
+ background: url(images/titleBar.png) #e9e9e9 repeat-y right;
+ border-right: 1px solid #cccccc;
+ padding: 0px;
+}
+
+.soria .dojoxGrid-rowbar-inner {
+ border: none;
+ border-bottom: 1px solid #cccccc;
+}
+
+.soria .dojoxGrid-rowbar-over {
+ background: url(images/titleBarActive.png) #e9e9e9 repeat-y right;
+}
+
+.soria .dojoxGrid-rowbar-selected {
+ background-color: #D9E8F9;
+ background-image: none;
+ background: url(../../../dijit/themes/soria/images/titleBar.png) #dddddd repeat-x top;
+ border-right: 1px solid #cccccc;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+/* rows */
+
+.soria .dojoxGrid-row {
+ position: relative;
+ width: 9000em;
+}
+
+.soria .dojoxGrid-row {
+ border: none;
+ border-left: none;
+ border-right: none;
+ background-color: white;
+ border-top: none;
+}
+
+.soria .dojoxGrid-row-over {
+ border-top-color: #cccccc;
+ border-bottom-color: #cccccc;
+}
+
+.soria .dojoxGrid-row-over .dojoxGrid-cell {
+ background-color: #60a1ea;
+ color:#fff;
+}
+
+.soria .dojoxGrid-row-odd {
+ background-color: #f2f5f9;
+ /*background-color: #F9F7E8;*/
+}
+
+.soria .dojoxGrid-row-selected {
+ background-color: #aec7e3;
+}
+
+.soria .dojoxGrid-row-table {
+ table-layout: fixed;
+ width: 0;
+ border-collapse: collapse;
+}
+
+.soria .dojoxGrid-invisible {
+ visibility: hidden;
+}
+
+.soria .Xdojo-ie .dojoxGrid-invisible {
+ display: none;
+}
+
+.soria .dojoxGrid-invisible td, .dojoxGrid-header .dojoxGrid-invisible td {
+ border-top-width: 0;
+ border-bottom-width: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ height: 0;
+ overflow: hidden;
+}
+
+/* cells */
+
+.soria .dojoxGrid-cell {
+ border: 1px dotted #D5CDB5;
+ padding: 3px 3px 3px 3px;
+ text-align: left;
+ overflow: hidden;
+}
+
+.dj_ie6 .soria .dojoxGrid-cell {
+ border: 1px solid white;
+ border-right: 1px solid #D5CDB5;
+}
+
+.soria .dojoxGrid-cell-focus {
+ border: 1px dotted #a6a6a6;
+}
+
+.soria .dojoxGrid-cell-over {
+ border: 1px dotted #a6a6a6;
+}
+
+.soria .dojoxGrid-cell-focus.dojoxGrid-cell-over {
+ border: 1px dotted #595959;
+}
+
+.soria .dojoxGrid-cell-clip {
+ width: 100%;
+ overflow: hidden;
+ white-space:nowrap;
+ text-overflow: ellipsis;
+}
+
+/* editing */
+
+/* FIXME: these colors are off! */
+.soria .dojoxGrid-row-editing td {
+ /* background-color: #F4FFF4; */
+ background-color: #60a1ea;
+ /* padding: 0px 3px 0px 3px; */
+}
+
+.soria .dojoxGrid-row-inserting td {
+ background-color: #F4FFF4;
+}
+.soria .dojoxGrid-row-inflight td {
+ background-color: #F2F7B7;
+}
+.soria .dojoxGrid-row-error td {
+ background-color: #F8B8B6;
+}
+
+.soria .dojoxGrid-input,
+.soria .dojoxGrid-select,
+.soria .dojoxGrid-textarea {
+ margin: 0;
+ padding: 0px;
+ border-style: none;
+ width: 100%;
+ font-size: 100%;
+ font-family: inherit;
+}
+
+.dojoxGrid-hidden-focus {
+ position: absolute;
+ left: -1000px;
+ top: -1000px;
+ height: 0px, width: 0px;
+}
+
+.dijit_a11y .dojoxGrid-rowbar-selected {
+ border-top: 1px solid white;
+ border-bottom: 1px dashed black;
+ border-top: 0;
+ background: none;
+}
+
+.dijit_a11y .dojoxGrid-rowbar-selected .dojoxGrid-rowbar-inner {
+ border: 0;
+ border-top: 1px solid white;
+}
+
+.dijit_a11y .dojoxGrid-row-selected {
+ border-bottom: 1px dashed black;
+}
diff --git a/includes/js/dojox/grid/_grid/tundraGrid.css b/includes/js/dojox/grid/_grid/tundraGrid.css
new file mode 100644
index 0000000..d7b7a5f
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/tundraGrid.css
@@ -0,0 +1,215 @@
+.tundra .dojoxGrid {
+ position: relative;
+ background-color: #e9e9e9;
+ font-size: 0.85em;
+ -moz-outline-style: none;
+ outline: none;
+ overflow: hidden;
+ height: 0;
+}
+.tundra .dojoxGrid table {
+ padding: 0;
+}
+.tundra .dojoxGrid td {
+ -moz-outline: none;
+}
+.tundra .dojoxGrid-master-header {
+ position: relative;
+}
+.tundra .dojoxGrid-master-view {
+ position: relative;
+}
+.tundra .dojoxGrid-view {
+ position: absolute;
+ overflow: hidden;
+}
+.tundra .dojoxGrid-header {
+ position: absolute;
+ overflow: hidden;
+}
+.tundra .dojoxGrid-header {
+ background-color: #e9e9e9;
+}
+.tundra .dojoxGrid-header table {
+ text-align: center;
+}
+.tundra .dojoxGrid-header .dojoxGrid-cell-content {
+ text-align: center;
+}
+.tundra .dojoxGrid-header .dojoxGrid-cell {
+ border: 1px solid transparent;
+
+ border-color: white #ACA899 #919191 white;
+ background: url(../../../dijit/themes/tundra/images/tabEnabled.png) #e9e9e9 repeat-x top;
+ padding-bottom: 2px;
+ color: #000 !important;
+}
+.tundra .dojoxGrid-header .dojoxGrid-cell-over {
+ background: url(../../../dijit/themes/tundra/images/tabHover.png) #e9e9e9 repeat-x top;
+ color: #000 !important;
+}
+.tundra .dojoxGrid-sort-down {
+ background: url(../../../dijit/themes/tundra/images/arrowDown.png) right no-repeat;
+ padding-left: 0px;
+ margin-left: 0px;
+}
+.tundra .dojoxGrid-sort-up {
+ background: url(../../../dijit/themes/tundra/images/arrowUp.png) right no-repeat;
+ padding-left: 0px;
+ margin-left: 0px;
+}
+.tundra .gridArrowButtonChar {
+ display:none !important;
+}
+.dijit_a11y .gridArrowButtonChar {
+ display:inline !important;
+}
+.tundra .dojoxGrid-scrollbox {
+ position: relative;
+ overflow: scroll;
+ background-color: #fefefe;
+ width: 100%;
+}
+.tundra .dojoxGrid-content {
+ position: relative;
+ overflow: hidden;
+ -moz-outline-style: none;
+ outline: none;
+}
+.tundra .dojoxGrid-rowbar {
+ border: none;
+
+ background: url(images/tabEnabled_rotated.png) #e9e9e9 repeat-y right;
+ border-right: 1px solid #cccccc;
+ padding: 0px;
+}
+.tundra .dojoxGrid-rowbar-inner {
+ border: none;
+ border-bottom: 1px solid #cccccc;
+}
+.tundra .dojoxGrid-rowbar-over {
+ background: url(images/tabHover_rotated.png) #e9e9e9 repeat-y right;
+}
+.tundra .dojoxGrid-rowbar-selected {
+ background-color: #D9E8F9;
+ background-image: none;
+ background: url(../../../dijit/themes/tundra/images/tabDisabled.png) #dddddd repeat-x top;
+ border-right: 1px solid #cccccc;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+.tundra .dojoxGrid-row {
+ position: relative;
+ width: 9000em;
+}
+.tundra .dojoxGrid-row {
+ border: none;
+ border-left: none;
+ border-right: none;
+ background-color: white;
+ border-top: none;
+}
+.tundra .dojoxGrid-row-over {
+ border-top-color: #cccccc;
+ border-bottom-color: #cccccc;
+}
+.tundra .dojoxGrid-row-over .dojoxGrid-cell {
+ background-color: #60a1ea;
+ color:#fff;
+
+}
+.tundra .dojoxGrid-row-odd {
+ background-color: #f2f5f9;
+
+}
+.tundra .dojoxGrid-row-selected {
+ background-color: #aec7e3;
+
+}
+.tundra .dojoxGrid-row-table {
+ table-layout: fixed;
+ width: 0;
+ border-collapse: collapse;
+}
+.tundra .dojoxGrid-invisible {
+ visibility: hidden;
+}
+.tundra .Xdojo-ie .dojoxGrid-invisible {
+ display: none;
+}
+.tundra .dojoxGrid-invisible td, .dojoxGrid-header .dojoxGrid-invisible td {
+ border-top-width: 0;
+ border-bottom-width: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ height: 0;
+ overflow: hidden;
+}
+.tundra .dojoxGrid-cell {
+ border: 1px dotted #D5CDB5;
+ padding: 3px 3px 3px 3px;
+ text-align: left;
+ overflow: hidden;
+}
+.dj_ie6 .tundra .dojoxGrid-cell {
+ border: 1px solid white;
+ border-right: 1px solid #D5CDB5;
+}
+.tundra .dojoxGrid-cell-focus {
+ border: 1px dotted #a6a6a6;
+}
+.tundra .dojoxGrid-cell-over {
+ border: 1px dotted #a6a6a6;
+}
+.tundra .dojoxGrid-cell-focus.dojoxGrid-cell-over {
+ border: 1px dotted #595959;
+}
+.tundra .dojoxGrid-cell-clip {
+ width: 100%;
+ overflow: hidden;
+ white-space:nowrap;
+ text-overflow: ellipsis;
+}
+.tundra .dojoxGrid-row-editing td {
+
+ background-color: #60a1ea;
+
+}
+.tundra .dojoxGrid-row-inserting td {
+ background-color: #F4FFF4;
+}
+.tundra .dojoxGrid-row-inflight td {
+ background-color: #F2F7B7;
+}
+.tundra .dojoxGrid-row-error td {
+ background-color: #F8B8B6;
+}
+.tundra .dojoxGrid-input,
+.tundra .dojoxGrid-select,
+.tundra .dojoxGrid-textarea {
+ margin: 0;
+ padding: 0px;
+ border-style: none;
+ width: 100%;
+ font-size: 100%;
+ font-family: inherit;
+}
+.dojoxGrid-hidden-focus {
+ position: absolute;
+ left: -1000px;
+ top: -1000px;
+ height: 0px, width: 0px;
+}
+.dijit_a11y .dojoxGrid-rowbar-selected {
+ border-top: 1px solid white;
+ border-bottom: 1px dashed black;
+ border-top: 0;
+ background: none;
+}
+.dijit_a11y .dojoxGrid-rowbar-selected .dojoxGrid-rowbar-inner {
+ border: 0;
+ border-top: 1px solid white;
+}
+.dijit_a11y .dojoxGrid-row-selected {
+ border-bottom: 1px dashed black;
+}
diff --git a/includes/js/dojox/grid/_grid/tundraGrid.css.commented.css b/includes/js/dojox/grid/_grid/tundraGrid.css.commented.css
new file mode 100644
index 0000000..a282f58
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/tundraGrid.css.commented.css
@@ -0,0 +1,281 @@
+.tundra .dojoxGrid {
+ position: relative;
+ background-color: #e9e9e9;
+ font-size: 0.85em; /* inherit font-family from dojo.css */
+ -moz-outline-style: none;
+ outline: none;
+ overflow: hidden;
+ height: 0;
+}
+
+.tundra .dojoxGrid table {
+ padding: 0;
+}
+
+.tundra .dojoxGrid td {
+ -moz-outline: none;
+}
+
+/* master header */
+
+.tundra .dojoxGrid-master-header {
+ position: relative;
+}
+
+/* master view */
+
+.tundra .dojoxGrid-master-view {
+ position: relative;
+}
+
+/* views */
+
+.tundra .dojoxGrid-view {
+ position: absolute;
+ overflow: hidden;
+}
+
+/* header */
+
+.tundra .dojoxGrid-header {
+ position: absolute;
+ overflow: hidden;
+}
+
+.tundra .dojoxGrid-header {
+ background-color: #e9e9e9;
+}
+
+.tundra .dojoxGrid-header table {
+ text-align: center;
+}
+
+.tundra .dojoxGrid-header .dojoxGrid-cell-content {
+ text-align: center;
+}
+
+.tundra .dojoxGrid-header .dojoxGrid-cell {
+ border: 1px solid transparent;
+ /* border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB; */
+ border-color: white #ACA899 #919191 white;
+ background: url(../../../dijit/themes/tundra/images/tabEnabled.png) #e9e9e9 repeat-x top;
+ padding-bottom: 2px;
+ color: #000 !important;
+}
+
+.tundra .dojoxGrid-header .dojoxGrid-cell-over {
+ background: url(../../../dijit/themes/tundra/images/tabHover.png) #e9e9e9 repeat-x top;
+ color: #000 !important;
+}
+
+.tundra .dojoxGrid-sort-down {
+ background: url(../../../dijit/themes/tundra/images/arrowDown.png) right no-repeat;
+ padding-left: 0px;
+ margin-left: 0px;
+}
+
+.tundra .dojoxGrid-sort-up {
+ background: url(../../../dijit/themes/tundra/images/arrowUp.png) right no-repeat;
+ padding-left: 0px;
+ margin-left: 0px;
+}
+
+.tundra .gridArrowButtonChar {
+ display:none !important;
+}
+.dijit_a11y .gridArrowButtonChar {
+ display:inline !important;
+}
+
+/* content */
+
+.tundra .dojoxGrid-scrollbox {
+ position: relative;
+ overflow: scroll;
+ background-color: #fefefe;
+ width: 100%;
+}
+
+.tundra .dojoxGrid-content {
+ position: relative;
+ overflow: hidden;
+ -moz-outline-style: none;
+ outline: none;
+}
+
+/* rowbar */
+
+.tundra .dojoxGrid-rowbar {
+ border: none;
+ /*
+ border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
+ */
+ background: url(images/tabEnabled_rotated.png) #e9e9e9 repeat-y right;
+ border-right: 1px solid #cccccc;
+ padding: 0px;
+}
+
+.tundra .dojoxGrid-rowbar-inner {
+ border: none;
+ border-bottom: 1px solid #cccccc;
+}
+
+.tundra .dojoxGrid-rowbar-over {
+ background: url(images/tabHover_rotated.png) #e9e9e9 repeat-y right;
+}
+
+.tundra .dojoxGrid-rowbar-selected {
+ background-color: #D9E8F9;
+ background-image: none;
+ background: url(../../../dijit/themes/tundra/images/tabDisabled.png) #dddddd repeat-x top;
+ border-right: 1px solid #cccccc;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+/* rows */
+
+.tundra .dojoxGrid-row {
+ position: relative;
+ width: 9000em;
+}
+
+.tundra .dojoxGrid-row {
+ border: none;
+ border-left: none;
+ border-right: none;
+ background-color: white;
+ border-top: none;
+}
+
+.tundra .dojoxGrid-row-over {
+ border-top-color: #cccccc;
+ border-bottom-color: #cccccc;
+}
+
+.tundra .dojoxGrid-row-over .dojoxGrid-cell {
+ background-color: #60a1ea;
+ color:#fff;
+ /*background: url(../../../dijit/themes/tundra/images/tabEnabled.png) #e9e9e9 repeat-x top;*/
+}
+
+.tundra .dojoxGrid-row-odd {
+ background-color: #f2f5f9;
+ /*background-color: #F9F7E8;*/
+}
+
+.tundra .dojoxGrid-row-selected {
+ background-color: #aec7e3;
+ /*
+ background: url(../../../dijit/themes/tundra/images/tabDisabled.png) #dddddd repeat-x top;
+ */
+}
+
+.tundra .dojoxGrid-row-table {
+ table-layout: fixed;
+ width: 0;
+ border-collapse: collapse;
+}
+
+.tundra .dojoxGrid-invisible {
+ visibility: hidden;
+}
+
+.tundra .Xdojo-ie .dojoxGrid-invisible {
+ display: none;
+}
+
+.tundra .dojoxGrid-invisible td, .dojoxGrid-header .dojoxGrid-invisible td {
+ border-top-width: 0;
+ border-bottom-width: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ height: 0;
+ overflow: hidden;
+}
+
+/* cells */
+
+.tundra .dojoxGrid-cell {
+ border: 1px dotted #D5CDB5;
+ padding: 3px 3px 3px 3px;
+ text-align: left;
+ overflow: hidden;
+}
+
+.dj_ie6 .tundra .dojoxGrid-cell {
+ border: 1px solid white;
+ border-right: 1px solid #D5CDB5;
+}
+
+.tundra .dojoxGrid-cell-focus {
+ border: 1px dotted #a6a6a6;
+}
+
+.tundra .dojoxGrid-cell-over {
+ border: 1px dotted #a6a6a6;
+}
+
+.tundra .dojoxGrid-cell-focus.dojoxGrid-cell-over {
+ border: 1px dotted #595959;
+}
+
+.tundra .dojoxGrid-cell-clip {
+ width: 100%;
+ overflow: hidden;
+ white-space:nowrap;
+ text-overflow: ellipsis;
+}
+
+/* editing */
+
+/* FIXME: these colors are off! */
+.tundra .dojoxGrid-row-editing td {
+ /* background-color: #F4FFF4; */
+ background-color: #60a1ea;
+ /* padding: 0px 3px 0px 3px; */
+}
+
+.tundra .dojoxGrid-row-inserting td {
+ background-color: #F4FFF4;
+}
+.tundra .dojoxGrid-row-inflight td {
+ background-color: #F2F7B7;
+}
+.tundra .dojoxGrid-row-error td {
+ background-color: #F8B8B6;
+}
+
+.tundra .dojoxGrid-input,
+.tundra .dojoxGrid-select,
+.tundra .dojoxGrid-textarea {
+ margin: 0;
+ padding: 0px;
+ border-style: none;
+ width: 100%;
+ font-size: 100%;
+ font-family: inherit;
+}
+
+.dojoxGrid-hidden-focus {
+ position: absolute;
+ left: -1000px;
+ top: -1000px;
+ height: 0px, width: 0px;
+}
+
+.dijit_a11y .dojoxGrid-rowbar-selected {
+ border-top: 1px solid white;
+ border-bottom: 1px dashed black;
+ border-top: 0;
+ background: none;
+}
+
+.dijit_a11y .dojoxGrid-rowbar-selected .dojoxGrid-rowbar-inner {
+ border: 0;
+ border-top: 1px solid white;
+}
+
+.dijit_a11y .dojoxGrid-row-selected {
+ border-bottom: 1px dashed black;
+}
diff --git a/includes/js/dojox/grid/_grid/view.js b/includes/js/dojox/grid/_grid/view.js
new file mode 100644
index 0000000..7f669cd
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/view.js
@@ -0,0 +1,336 @@
+if(!dojo._hasResource["dojox.grid._grid.view"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._grid.view"] = true;
+dojo.provide("dojox.grid._grid.view");
+
+dojo.require("dijit._Widget");
+dojo.require("dijit._Templated");
+dojo.require("dojox.grid._grid.builder");
+
+dojo.declare('dojox.GridView',
+ [dijit._Widget, dijit._Templated],
+ {
+ // summary:
+ // A collection of grid columns. A grid is comprised of a set of views that stack horizontally.
+ // Grid creates views automatically based on grid's layout structure.
+ // Users should typically not need to access individual views directly.
+ //
+ // defaultWidth: String
+ // Default widget of the view
+ defaultWidth: "18em",
+
+ // viewWidth: String
+ // Width for the view, in valid css unit
+ viewWidth: "",
+
+ templateString:"<div class=\"dojoxGrid-view\">\n\t<div class=\"dojoxGrid-header\" dojoAttachPoint=\"headerNode\">\n\t\t<div dojoAttachPoint=\"headerNodeContainer\" style=\"width:9000em\">\n\t\t\t<div dojoAttachPoint=\"headerContentNode\"></div>\n\t\t</div>\n\t</div>\n\t<input type=\"checkbox\" class=\"dojoxGrid-hidden-focus\" dojoAttachPoint=\"hiddenFocusNode\" />\n\t<input type=\"checkbox\" class=\"dojoxGrid-hidden-focus\" />\n\t<div class=\"dojoxGrid-scrollbox\" dojoAttachPoint=\"scrollboxNode\">\n\t\t<div class=\"dojoxGrid-content\" dojoAttachPoint=\"contentNode\" hidefocus=\"hidefocus\"></div>\n\t</div>\n</div>\n",
+
+ themeable: false,
+ classTag: 'dojoxGrid',
+ marginBottom: 0,
+ rowPad: 2,
+
+ postMixInProperties: function(){
+ this.rowNodes = [];
+ },
+
+ postCreate: function(){
+ this.connect(this.scrollboxNode,"onscroll","doscroll");
+ dojox.grid.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
+ dojox.grid.funnelEvents(this.headerNode, this, "doHeaderEvent", [ 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
+ this.content = new dojox.grid.contentBuilder(this);
+ this.header = new dojox.grid.headerBuilder(this);
+ //BiDi: in RTL case, style width='9000em' causes scrolling problem in head node
+ if(!dojo._isBodyLtr()){
+ this.headerNodeContainer.style.width = "";
+ }
+ },
+
+ destroy: function(){
+ dojox.grid.removeNode(this.headerNode);
+ this.inherited("destroy", arguments);
+ },
+
+ // focus
+ focus: function(){
+ if(dojo.isSafari || dojo.isOpera){
+ this.hiddenFocusNode.focus();
+ }else{
+ this.scrollboxNode.focus();
+ }
+ },
+
+ setStructure: function(inStructure){
+ var vs = this.structure = inStructure;
+ // FIXME: similar logic is duplicated in layout
+ if(vs.width && !isNaN(vs.width)){
+ this.viewWidth = vs.width + 'em';
+ }else{
+ this.viewWidth = vs.width || this.viewWidth; //|| this.defaultWidth;
+ }
+ this.onBeforeRow = vs.onBeforeRow;
+ this.noscroll = vs.noscroll;
+ if(this.noscroll){
+ this.scrollboxNode.style.overflow = "hidden";
+ }
+ // bookkeeping
+ this.testFlexCells();
+ // accomodate new structure
+ this.updateStructure();
+ },
+
+ testFlexCells: function(){
+ // FIXME: cheater, this function does double duty as initializer and tester
+ this.flexCells = false;
+ for(var j=0, row; (row=this.structure.rows[j]); j++){
+ for(var i=0, cell; (cell=row[i]); i++){
+ cell.view = this;
+ this.flexCells = this.flexCells || cell.isFlex();
+ }
+ }
+ return this.flexCells;
+ },
+
+ updateStructure: function(){
+ // header builder needs to update table map
+ this.header.update();
+ // content builder needs to update markup cache
+ this.content.update();
+ },
+
+ getScrollbarWidth: function(){
+ return (this.noscroll ? 0 : dojox.grid.getScrollbarWidth()); // Integer
+ },
+
+ getColumnsWidth: function(){
+ return this.headerContentNode.firstChild.offsetWidth; // Integer
+ },
+
+ getWidth: function(){
+ return this.viewWidth || (this.getColumnsWidth()+this.getScrollbarWidth()) +'px'; // String
+ },
+
+ getContentWidth: function(){
+ return Math.max(0, dojo._getContentBox(this.domNode).w - this.getScrollbarWidth()) + 'px'; // String
+ },
+
+ render: function(){
+ this.scrollboxNode.style.height = '';
+ this.renderHeader();
+ },
+
+ renderHeader: function(){
+ this.headerContentNode.innerHTML = this.header.generateHtml(this._getHeaderContent);
+ },
+
+ // note: not called in 'view' context
+ _getHeaderContent: function(inCell){
+ var n = inCell.name || inCell.grid.getCellName(inCell);
+ if(inCell.index != inCell.grid.getSortIndex()){
+ return n;
+ }
+ return [ '<div class="', inCell.grid.sortInfo > 0 ? 'dojoxGrid-sort-down' : 'dojoxGrid-sort-up', '"><div class="gridArrowButtonChar">', inCell.grid.sortInfo > 0 ? '&#9660;' : '&#9650;', '</div>', n, '</div>' ].join('');
+ },
+
+ resize: function(){
+ this.adaptHeight();
+ this.adaptWidth();
+ },
+
+ hasScrollbar: function(){
+ return (this.scrollboxNode.clientHeight != this.scrollboxNode.offsetHeight); // Boolean
+ },
+
+ adaptHeight: function(){
+ if(!this.grid.autoHeight){
+ var h = this.domNode.clientHeight;
+ if(!this.hasScrollbar()){ // no scrollbar is rendered
+ h -= dojox.grid.getScrollbarWidth();
+ }
+ dojox.grid.setStyleHeightPx(this.scrollboxNode, h);
+ }
+ },
+
+ adaptWidth: function(){
+ if(this.flexCells){
+ // the view content width
+ this.contentWidth = this.getContentWidth();
+ this.headerContentNode.firstChild.style.width = this.contentWidth;
+ }
+ // FIXME: it should be easier to get w from this.scrollboxNode.clientWidth,
+ // but clientWidth seemingly does not include scrollbar width in some cases
+ var w = this.scrollboxNode.offsetWidth - this.getScrollbarWidth();
+ w = Math.max(w, this.getColumnsWidth()) + 'px';
+ with(this.contentNode){
+ style.width = '';
+ offsetWidth;
+ style.width = w;
+ }
+ },
+
+ setSize: function(w, h){
+ with(this.domNode.style){
+ if(w){
+ width = w;
+ }
+ height = (h >= 0 ? h + 'px' : '');
+ }
+ with(this.headerNode.style){
+ if(w){
+ width = w;
+ }
+ }
+ },
+
+ renderRow: function(inRowIndex, inHeightPx){
+ var rowNode = this.createRowNode(inRowIndex);
+ this.buildRow(inRowIndex, rowNode, inHeightPx);
+ this.grid.edit.restore(this, inRowIndex);
+ return rowNode;
+ },
+
+ createRowNode: function(inRowIndex){
+ var node = document.createElement("div");
+ node.className = this.classTag + '-row';
+ node[dojox.grid.gridViewTag] = this.id;
+ node[dojox.grid.rowIndexTag] = inRowIndex;
+ this.rowNodes[inRowIndex] = node;
+ return node;
+ },
+
+ buildRow: function(inRowIndex, inRowNode){
+ this.buildRowContent(inRowIndex, inRowNode);
+ this.styleRow(inRowIndex, inRowNode);
+ },
+
+ buildRowContent: function(inRowIndex, inRowNode){
+ inRowNode.innerHTML = this.content.generateHtml(inRowIndex, inRowIndex);
+ if(this.flexCells){
+ // FIXME: accessing firstChild here breaks encapsulation
+ inRowNode.firstChild.style.width = this.contentWidth;
+ }
+ },
+
+ rowRemoved:function(inRowIndex){
+ this.grid.edit.save(this, inRowIndex);
+ delete this.rowNodes[inRowIndex];
+ },
+
+ getRowNode: function(inRowIndex){
+ return this.rowNodes[inRowIndex];
+ },
+
+ getCellNode: function(inRowIndex, inCellIndex){
+ var row = this.getRowNode(inRowIndex);
+ if(row){
+ return this.content.getCellNode(row, inCellIndex);
+ }
+ },
+
+ // styling
+ styleRow: function(inRowIndex, inRowNode){
+ inRowNode._style = dojox.grid.getStyleText(inRowNode);
+ this.styleRowNode(inRowIndex, inRowNode);
+ },
+
+ styleRowNode: function(inRowIndex, inRowNode){
+ if(inRowNode){
+ this.doStyleRowNode(inRowIndex, inRowNode);
+ }
+ },
+
+ doStyleRowNode: function(inRowIndex, inRowNode){
+ this.grid.styleRowNode(inRowIndex, inRowNode);
+ },
+
+ // updating
+ updateRow: function(inRowIndex, inHeightPx, inPageNode){
+ var rowNode = this.getRowNode(inRowIndex);
+ if(rowNode){
+ rowNode.style.height = '';
+ this.buildRow(inRowIndex, rowNode);
+ }
+ return rowNode;
+ },
+
+ updateRowStyles: function(inRowIndex){
+ this.styleRowNode(inRowIndex, this.getRowNode(inRowIndex));
+ },
+
+ // scrolling
+ lastTop: 0,
+ firstScroll:0,
+
+ doscroll: function(inEvent){
+ //var s = dojo.marginBox(this.headerContentNode.firstChild);
+ var isLtr = dojo._isBodyLtr();
+ if(this.firstScroll < 2){
+ if((!isLtr && this.firstScroll == 1) || (isLtr && this.firstScroll == 0)){
+ var s = dojo.marginBox(this.headerNodeContainer);
+ if(dojo.isIE){
+ this.headerNodeContainer.style.width = s.w + this.getScrollbarWidth() + 'px';
+ }else if(dojo.isMoz){
+ //TODO currently only for FF, not sure for safari and opera
+ this.headerNodeContainer.style.width = s.w - this.getScrollbarWidth() + 'px';
+ //this.headerNodeContainer.style.width = s.w + 'px';
+ //set scroll to right in FF
+ if(isLtr){
+ this.scrollboxNode.scrollLeft = this.scrollboxNode.scrollWidth - this.scrollboxNode.clientWidth;
+ }else{
+ this.scrollboxNode.scrollLeft = this.scrollboxNode.clientWidth - this.scrollboxNode.scrollWidth;
+ }
+ }
+ }
+ this.firstScroll++;
+ }
+ this.headerNode.scrollLeft = this.scrollboxNode.scrollLeft;
+ // 'lastTop' is a semaphore to prevent feedback-loop with setScrollTop below
+ var top = this.scrollboxNode.scrollTop;
+ if(top != this.lastTop){
+ this.grid.scrollTo(top);
+ }
+ },
+
+ setScrollTop: function(inTop){
+ // 'lastTop' is a semaphore to prevent feedback-loop with doScroll above
+ this.lastTop = inTop;
+ this.scrollboxNode.scrollTop = inTop;
+ return this.scrollboxNode.scrollTop;
+ },
+
+ // event handlers (direct from DOM)
+ doContentEvent: function(e){
+ if(this.content.decorateEvent(e)){
+ this.grid.onContentEvent(e);
+ }
+ },
+
+ doHeaderEvent: function(e){
+ if(this.header.decorateEvent(e)){
+ this.grid.onHeaderEvent(e);
+ }
+ },
+
+ // event dispatch(from Grid)
+ dispatchContentEvent: function(e){
+ return this.content.dispatchEvent(e);
+ },
+
+ dispatchHeaderEvent: function(e){
+ return this.header.dispatchEvent(e);
+ },
+
+ // column resizing
+ setColWidth: function(inIndex, inWidth){
+ this.grid.setCellWidth(inIndex, inWidth + 'px');
+ },
+
+ update: function(){
+ var left = this.scrollboxNode.scrollLeft;
+ this.content.update();
+ this.grid.update();
+ this.scrollboxNode.scrollLeft = left;
+ this.headerNode.scrollLeft = left;
+ }
+});
+
+}
diff --git a/includes/js/dojox/grid/_grid/views.js b/includes/js/dojox/grid/_grid/views.js
new file mode 100644
index 0000000..d13bbb7
--- /dev/null
+++ b/includes/js/dojox/grid/_grid/views.js
@@ -0,0 +1,277 @@
+if(!dojo._hasResource["dojox.grid._grid.views"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid._grid.views"] = true;
+dojo.provide("dojox.grid._grid.views");
+
+dojo.declare('dojox.grid.views', null, {
+ // summary:
+ // A collection of grid views. Owned by grid and used internally for managing grid views.
+ // description:
+ // Grid creates views automatically based on grid's layout structure.
+ // Users should typically not need to access individual views or the views collection directly.
+ constructor: function(inGrid){
+ this.grid = inGrid;
+ },
+
+ defaultWidth: 200,
+
+ views: [],
+
+ // operations
+ resize: function(){
+ this.onEach("resize");
+ },
+
+ render: function(){
+ this.onEach("render");
+ },
+
+ // views
+ addView: function(inView){
+ inView.idx = this.views.length;
+ this.views.push(inView);
+ },
+
+ destroyViews: function(){
+ for (var i=0, v; v=this.views[i]; i++)
+ v.destroy();
+ this.views = [];
+ },
+
+ getContentNodes: function(){
+ var nodes = [];
+ for(var i=0, v; v=this.views[i]; i++){
+ nodes.push(v.contentNode);
+ }
+ return nodes;
+ },
+
+ forEach: function(inCallback){
+ for(var i=0, v; v=this.views[i]; i++){
+ inCallback(v, i);
+ }
+ },
+
+ onEach: function(inMethod, inArgs){
+ inArgs = inArgs || [];
+ for(var i=0, v; v=this.views[i]; i++){
+ if(inMethod in v){
+ v[inMethod].apply(v, inArgs);
+ }
+ }
+ },
+
+ // layout
+ normalizeHeaderNodeHeight: function(){
+ var rowNodes = [];
+ for(var i=0, v; (v=this.views[i]); i++){
+ if(v.headerContentNode.firstChild){
+ rowNodes.push(v.headerContentNode)
+ };
+ }
+ this.normalizeRowNodeHeights(rowNodes);
+ },
+
+ normalizeRowNodeHeights: function(inRowNodes){
+ var h = 0;
+ for(var i=0, n, o; (n=inRowNodes[i]); i++){
+ h = Math.max(h, (n.firstChild.clientHeight)||(n.firstChild.offsetHeight));
+ }
+ h = (h >= 0 ? h : 0);
+ //
+ var hpx = h + 'px';
+ for(var i=0, n; (n=inRowNodes[i]); i++){
+ if(n.firstChild.clientHeight!=h){
+ n.firstChild.style.height = hpx;
+ }
+ }
+ //
+ //console.log('normalizeRowNodeHeights ', h);
+ //
+ // querying the height here seems to help scroller measure the page on IE
+ if(inRowNodes&&inRowNodes[0]){
+ inRowNodes[0].parentNode.offsetHeight;
+ }
+ },
+
+ resetHeaderNodeHeight: function(){
+ for(var i=0, v, n; (v=this.views[i]); i++){
+ n = v.headerContentNode.firstChild;
+ if(n)
+ n.style.height = "";
+ }
+ },
+
+ renormalizeRow: function(inRowIndex){
+ var rowNodes = [];
+ for(var i=0, v, n; (v=this.views[i])&&(n=v.getRowNode(inRowIndex)); i++){
+ n.firstChild.style.height = '';
+ rowNodes.push(n);
+ }
+ this.normalizeRowNodeHeights(rowNodes);
+ },
+
+ getViewWidth: function(inIndex){
+ return this.views[inIndex].getWidth() || this.defaultWidth;
+ },
+
+ // must be called after view widths are properly set or height can be miscalculated
+ // if there are flex columns
+ measureHeader: function(){
+ // need to reset view header heights so they are properly measured.
+ this.resetHeaderNodeHeight();
+ this.forEach(function(inView){
+ inView.headerContentNode.style.height = '';
+ });
+ var h = 0;
+ // calculate maximum view header height
+ this.forEach(function(inView){
+ h = Math.max(inView.headerNode.offsetHeight, h);
+ });
+ return h;
+ },
+
+ measureContent: function(){
+ var h = 0;
+ this.forEach(function(inView) {
+ h = Math.max(inView.domNode.offsetHeight, h);
+ });
+ return h;
+ },
+
+ findClient: function(inAutoWidth){
+ // try to use user defined client
+ var c = this.grid.elasticView || -1;
+ // attempt to find implicit client
+ if(c < 0){
+ for(var i=1, v; (v=this.views[i]); i++){
+ if(v.viewWidth){
+ for(i=1; (v=this.views[i]); i++){
+ if(!v.viewWidth){
+ c = i;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ // client is in the middle by default
+ if(c < 0){
+ c = Math.floor(this.views.length / 2);
+ }
+ return c;
+ },
+
+ arrange: function(l, w){
+ var i, v, vw, len = this.views.length;
+ // find the client
+ var c = (w <= 0 ? len : this.findClient());
+ // layout views
+ var setPosition = function(v, l){
+ with(v.domNode.style){
+ if(!dojo._isBodyLtr()){
+ right = l + 'px';
+ }else{
+ left = l + 'px';
+ }
+ top = 0 + 'px';
+ }
+ with(v.headerNode.style){
+ if(!dojo._isBodyLtr()){
+ right = l + 'px';
+ }else{
+ left = l + 'px';
+ }
+ top = 0;
+ }
+ }
+ // for views left of the client
+ //BiDi TODO: The left and right should not appear in BIDI environment. Should be replaced with
+ //leading and tailing concept.
+ for(i=0; (v=this.views[i])&&(i<c); i++){
+ // get width
+ vw = this.getViewWidth(i);
+ // process boxes
+ v.setSize(vw, 0);
+ setPosition(v, l);
+ vw = v.domNode.offsetWidth;
+ // update position
+ l += vw;
+ }
+ // next view (is the client, i++ == c)
+ i++;
+ // start from the right edge
+ var r = w;
+ // for views right of the client (iterated from the right)
+ for(var j=len-1; (v=this.views[j])&&(i<=j); j--){
+ // get width
+ vw = this.getViewWidth(j);
+ // set size
+ v.setSize(vw, 0);
+ // measure in pixels
+ vw = v.domNode.offsetWidth;
+ // update position
+ r -= vw;
+ // set position
+ setPosition(v, r);
+ }
+ if(c<len){
+ v = this.views[c];
+ // position the client box between left and right boxes
+ vw = Math.max(1, r-l);
+ // set size
+ v.setSize(vw + 'px', 0);
+ setPosition(v, l);
+ }
+ return l;
+ },
+
+ // rendering
+ renderRow: function(inRowIndex, inNodes){
+ var rowNodes = [];
+ for(var i=0, v, n, rowNode; (v=this.views[i])&&(n=inNodes[i]); i++){
+ rowNode = v.renderRow(inRowIndex);
+ n.appendChild(rowNode);
+ rowNodes.push(rowNode);
+ }
+ this.normalizeRowNodeHeights(rowNodes);
+ },
+
+ rowRemoved: function(inRowIndex){
+ this.onEach("rowRemoved", [ inRowIndex ]);
+ },
+
+ // updating
+ updateRow: function(inRowIndex, inHeight){
+ for(var i=0, v; v=this.views[i]; i++){
+ v.updateRow(inRowIndex, inHeight);
+ }
+ this.renormalizeRow(inRowIndex);
+ },
+
+ updateRowStyles: function(inRowIndex){
+ this.onEach("updateRowStyles", [ inRowIndex ]);
+ },
+
+ // scrolling
+ setScrollTop: function(inTop){
+ var top = inTop;
+ for(var i=0, v; v=this.views[i]; i++){
+ top = v.setScrollTop(inTop);
+ }
+ return top;
+ //this.onEach("setScrollTop", [ inTop ]);
+ },
+
+ getFirstScrollingView: function(){
+ // summary: Returns the first grid view with a scroll bar
+ for(var i=0, v; (v=this.views[i]); i++){
+ if(v.hasScrollbar()){
+ return v;
+ }
+ }
+ }
+
+});
+
+}
diff --git a/includes/js/dojox/grid/resources/GridView.html b/includes/js/dojox/grid/resources/GridView.html
new file mode 100644
index 0000000..d86782d
--- /dev/null
+++ b/includes/js/dojox/grid/resources/GridView.html
@@ -0,0 +1,12 @@
+<div class="dojoxGrid-view">
+ <div class="dojoxGrid-header" dojoAttachPoint="headerNode">
+ <div dojoAttachPoint="headerNodeContainer" style="width:9000em">
+ <div dojoAttachPoint="headerContentNode"></div>
+ </div>
+ </div>
+ <input type="checkbox" class="dojoxGrid-hidden-focus" dojoAttachPoint="hiddenFocusNode" />
+ <input type="checkbox" class="dojoxGrid-hidden-focus" />
+ <div class="dojoxGrid-scrollbox" dojoAttachPoint="scrollboxNode">
+ <div class="dojoxGrid-content" dojoAttachPoint="contentNode" hidefocus="hidefocus"></div>
+ </div>
+</div> \ No newline at end of file
diff --git a/includes/js/dojox/grid/resources/VirtualGrid.html b/includes/js/dojox/grid/resources/VirtualGrid.html
new file mode 100644
index 0000000..7253108
--- /dev/null
+++ b/includes/js/dojox/grid/resources/VirtualGrid.html
@@ -0,0 +1,5 @@
+<div class="dojoxGrid" hidefocus="hidefocus" role="wairole:grid">
+ <div class="dojoxGrid-master-header" dojoAttachPoint="viewsHeaderNode"></div>
+ <div class="dojoxGrid-master-view" dojoAttachPoint="viewsNode"></div>
+ <span dojoAttachPoint="lastFocusNode" tabindex="0"></span>
+</div>
diff --git a/includes/js/dojox/grid/tests/databaseModel.js b/includes/js/dojox/grid/tests/databaseModel.js
new file mode 100644
index 0000000..3c879eb
--- /dev/null
+++ b/includes/js/dojox/grid/tests/databaseModel.js
@@ -0,0 +1,337 @@
+if(!dojo._hasResource["dojox.grid.tests.databaseModel"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.grid.tests.databaseModel"] = true;
+dojo.provide("dojox.grid.tests.databaseModel");
+dojo.require("dojox.grid._data.model");
+
+// Provides a sparse array that is also traversable inorder
+// with basic Array:
+// - iterating by index is slow for large sparse arrays
+// - for...in iteration is in order of element creation
+// maintains a secondary index for interating
+// over sparse elements inorder
+dojo.declare("dojox.grid.Sparse", null, {
+ constructor: function() {
+ this.clear();
+ },
+ clear: function() {
+ this.indices = [];
+ this.values = [];
+ },
+ length: function() {
+ return this.indices.length;
+ },
+ set: function(inIndex, inValue) {
+ for (var i=0,l=this.indices.length; i<l; i++) {
+ if (this.indices[i] >= inIndex)
+ break;
+ }
+ if (this.indices[i] != inIndex)
+ this.indices.splice(i, 0, inIndex);
+ this.values[inIndex] = inValue;
+ },
+ get: function(inIndex) {
+ return this.values[inIndex];
+ },
+ remove: function(inIndex) {
+ for (var i=0,l=this.indices.length; i<l; i++)
+ if (this.indices[i] == inIndex) {
+ this.indices.splice(i, 1);
+ break;
+ }
+ delete this.values[inIndex];
+ },
+ inorder: function(inFor) {
+ for (var i=0,l=this.indices.length, ix; i<l; i++) {
+ ix = this.indices[i];
+ if (inFor(this.values[ix], ix) === false)
+ break;
+ }
+ }
+});
+
+// sample custom model implementation that works with mysql server.
+dojo.declare("dojox.grid.data.DbTable", dojox.grid.data.Dynamic, {
+ delayedInsertCommit: true,
+ constructor: function(inFields, inData, inServer, inDatabase, inTable) {
+ this.server = inServer;
+ this.database = inDatabase;
+ this.table = inTable;
+ this.stateNames = ['inflight', 'inserting', 'removing', 'error'];
+ this.clearStates();
+ this.clearSort();
+ },
+ clearData: function() {
+ this.cache = [ ];
+ this.clearStates();
+ this.inherited(arguments);
+ },
+ clearStates: function() {
+ this.states = {};
+ for (var i=0, s; (s=this.stateNames[i]); i++) {
+ delete this.states[s];
+ this.states[s] = new dojox.grid.Sparse();
+ }
+ },
+ // row state information
+ getState: function(inRowIndex) {
+ for (var i=0, r={}, s; (s=this.stateNames[i]); i++)
+ r[s] = this.states[s].get(inRowIndex);
+ return r;
+ },
+ setState: function(inRowIndex, inState, inValue) {
+ this.states[inState].set(inRowIndex, inValue||true);
+ },
+ clearState: function(inRowIndex, inState) {
+ if (arguments.length == 1) {
+ for (var i=0, s; (s=this.stateNames[i]); i++)
+ this.states[s].remove(inRowIndex);
+ } else {
+ for (var i=1, l=arguments.length, arg; (i<l) &&((arg=arguments[i])!=undefined); i++)
+ this.states[arg].remove(inRowIndex);
+ }
+ },
+ setStateForIndexes: function(inRowIndexes, inState, inValue) {
+ for (var i=inRowIndexes.length-1, k; (i>=0) && ((k=inRowIndexes[i])!=undefined); i--)
+ this.setState(k, inState, inValue);
+ },
+ clearStateForIndexes: function(inRowIndexes, inState) {
+ for (var i=inRowIndexes.length-1, k; (i>=0) && ((k=inRowIndexes[i])!=undefined); i--)
+ this.clearState(k, inState);
+ },
+ //$ Return boolean stating whether or not an operation is in progress that may change row indexing.
+ isAddRemoving: function() {
+ return Boolean(this.states['inserting'].length() || this.states['removing'].length());
+ },
+ isInflight: function() {
+ return Boolean(this.states['inflight'].length());
+ },
+ //$ Return boolean stating if the model is currently undergoing any type of edit.
+ isEditing: function() {
+ for (var i=0, r={}, s; (s=this.stateNames[i]); i++)
+ if (this.states[s].length())
+ return true;
+ },
+ //$ Return true if ok to modify the given row. Override as needed, using model editing state information.
+ canModify: function(inRowIndex) {
+ return !this.getState(inRowIndex).inflight && !(this.isInflight() && this.isAddRemoving());
+ },
+ // server send / receive
+ getSendParams: function(inParams) {
+ var p = {
+ database: this.database || '',
+ table: this.table || ''
+ }
+ return dojo.mixin(p, inParams || {});
+ },
+ send: function(inAsync, inParams, inCallbacks) {
+ //console.log('send', inParams.command);
+ var p = this.getSendParams(inParams);
+ var d = dojo.xhrPost({
+ url: this.server,
+ content: p,
+ handleAs: 'json-comment-filtered',
+ contentType: "application/x-www-form-urlencoded; charset=utf-8",
+ sync: !inAsync
+ });
+ d.addCallbacks(dojo.hitch(this, "receive", inCallbacks), dojo.hitch(this, "receiveError", inCallbacks));
+ return d;
+ },
+ _callback: function(cb, eb, data) {
+ try{ cb && cb(data); }
+ catch(e){ eb && eb(data, e); }
+ },
+ receive: function(inCallbacks, inData) {
+ inCallbacks && this._callback(inCallbacks.callback, inCallbacks.errback, inData);
+ },
+ receiveError: function(inCallbacks, inErr) {
+ this._callback(inCallbacks.errback, null, inErr)
+ },
+ encodeRow: function(inParams, inRow, inPrefix) {
+ for (var i=0, l=inRow.length; i < l; i++)
+ inParams['_' + (inPrefix ? inPrefix : '') + i] = (inRow[i] ? inRow[i] : '');
+ },
+ measure: function() {
+ this.send(true, { command: 'info' }, { callback: dojo.hitch(this, this.callbacks.info) });
+ },
+ fetchRowCount: function(inCallbacks) {
+ this.send(true, { command: 'count' }, inCallbacks);
+ },
+ // server commits
+ commitEdit: function(inOldData, inNewData, inRowIndex, inCallbacks) {
+ this.setState(inRowIndex, "inflight", true);
+ var params = {command: 'update'};
+ this.encodeRow(params, inOldData, 'o');
+ this.encodeRow(params, inNewData);
+ this.send(true, params, inCallbacks);
+ },
+ commitInsert: function(inRowIndex, inNewData, inCallbacks) {
+ this.setState(inRowIndex, "inflight", true);
+ var params = {command: 'insert'};
+ this.encodeRow(params, inNewData);
+ this.send(true, params, inCallbacks);
+ },
+ // NOTE: supported only in tables with pk
+ commitDelete: function(inRows, inCallbacks) {
+ var params = {
+ command: 'delete',
+ count: inRows.length
+ }
+ var pk = this.getPkIndex();
+ if (pk < 0)
+ return;
+ for (var i=0; i < inRows.length; i++) {
+ params['_' + i] = inRows[i][pk];
+ }
+ this.send(true, params, inCallbacks);
+ },
+ getUpdateCallbacks: function(inRowIndex) {
+ return {
+ callback: dojo.hitch(this, this.callbacks.update, inRowIndex),
+ errback: dojo.hitch(this, this.callbacks.updateError, inRowIndex)
+ };
+ },
+ // primary key from fields
+ getPkIndex: function() {
+ for (var i=0, l=this.fields.count(), f; (i<l) && (f=this.fields.get(i)); i++)
+ if (f.Key = 'PRI')
+ return i;
+ return -1;
+ },
+ // model implementations
+ update: function(inOldData, inNewData, inRowIndex) {
+ var cbs = this.getUpdateCallbacks(inRowIndex);
+ if (this.getState(inRowIndex).inserting)
+ this.commitInsert(inRowIndex, inNewData, cbs);
+ else
+ this.commitEdit(this.cache[inRowIndex] || inOldData, inNewData, inRowIndex, cbs);
+ // set push data immediately to model so reflectd while committing
+ this.setRow(inNewData, inRowIndex);
+ },
+ insert: function(inData, inRowIndex) {
+ this.setState(inRowIndex, 'inserting', true);
+ if (!this.delayedInsertCommit)
+ this.commitInsert(inRowIndex, inData, this.getUpdateCallbacks(inRowIndex));
+ return this.inherited(arguments);
+ },
+ remove: function(inRowIndexes) {
+ var rows = [];
+ for (var i=0, r=0, indexes=[]; (r=inRowIndexes[i]) !== undefined; i++)
+ if (!this.getState(r).inserting) {
+ rows.push(this.getRow(r));
+ indexes.push(r);
+ this.setState(r, 'removing');
+ }
+ var cbs = {
+ callback: dojo.hitch(this, this.callbacks.remove, indexes),
+ errback: dojo.hitch(this, this.callbacks.removeError, indexes)
+ };
+ this.commitDelete(rows, cbs);
+ dojox.grid.data.Dynamic.prototype.remove.apply(this, arguments);
+ },
+ cancelModifyRow: function(inRowIndex) {
+ if (this.isDelayedInsert(inRowIndex)) {
+ this.removeInsert(inRowIndex);
+ } else
+ this.finishUpdate(inRowIndex);
+ },
+ finishUpdate: function(inRowIndex, inData) {
+ this.clearState(inRowIndex);
+ var d = (inData&&inData[0]) || this.cache[inRowIndex];
+ if (d)
+ this.setRow(d, inRowIndex);
+ delete this.cache[inRowIndex];
+ },
+ isDelayedInsert: function(inRowIndex) {
+ return (this.delayedInsertCommit && this.getState(inRowIndex).inserting);
+ },
+ removeInsert: function(inRowIndex) {
+ this.clearState(inRowIndex);
+ dojox.grid.data.Dynamic.prototype.remove.call(this, [inRowIndex]);
+ },
+ // request data
+ requestRows: function(inRowIndex, inCount) {
+ var params = {
+ command: 'select',
+ orderby: this.sortField,
+ desc: (this.sortDesc ? "true" : ''),
+ offset: inRowIndex,
+ limit: inCount
+ }
+ this.send(true, params, {callback: dojo.hitch(this, this.callbacks.rows, inRowIndex)});
+ },
+ // sorting
+ canSort: function () {
+ return true;
+ },
+ setSort: function(inSortIndex) {
+ this.sortField = this.fields.get(Math.abs(inSortIndex) - 1).name || inSortIndex;
+ this.sortDesc = (inSortIndex < 0);
+ },
+ sort: function(inSortIndex) {
+ this.setSort(inSortIndex);
+ this.clearData();
+ },
+ clearSort: function(){
+ this.sortField = '';
+ this.sortDesc = false;
+ },
+ endModifyRow: function(inRowIndex){
+ var cache = this.cache[inRowIndex];
+ var m = false;
+ if(cache){
+ var data = this.getRow(inRowIndex);
+ if(!dojox.grid.arrayCompare(cache, data)){
+ m = true;
+ this.update(cache, data, inRowIndex);
+ }
+ }
+ if (!m)
+ this.cancelModifyRow(inRowIndex);
+ },
+ // server callbacks (called with this == model)
+ callbacks: {
+ update: function(inRowIndex, inData) {
+ console.log('received update', arguments);
+ if (inData.error)
+ this.updateError(inData)
+ else
+ this.finishUpdate(inRowIndex, inData);
+ },
+ updateError: function(inRowIndex) {
+ this.clearState(inRowIndex, 'inflight');
+ this.setState(inRowIndex, "error", "update failed: " + inRowIndex);
+ this.rowChange(this.getRow(inRowIndex), inRowIndex);
+ },
+ remove: function(inRowIndexes) {
+ this.clearStateForIndexes(inRowIndexes);
+ },
+ removeError: function(inRowIndexes) {
+ this.clearStateForIndexes(inRowIndexes);
+ alert('Removal error. Please refresh.');
+ },
+ rows: function(inRowIndex, inData) {
+ //this.beginUpdate();
+ for (var i=0, l=inData.length; i<l; i++)
+ this.setRow(inData[i], inRowIndex + i);
+ //this.endUpdate();
+ //this.allChange();
+ },
+ count: function(inRowCount) {
+ this.count = Number(inRowCount);
+ this.clearData();
+ },
+ info: function(inInfo) {
+ this.fields.clear();
+ for (var i=0, c; (c=inInfo.columns[i]); i++) {
+ c.name = c.Field;
+ this.fields.set(i, c);
+ }
+ this.table = inInfo.table;
+ this.database = inInfo.database;
+ this.notify("MetaData", arguments);
+ this.callbacks.count.call(this, inInfo.count);
+ }
+ }
+});
+
+}
diff --git a/includes/js/dojox/grid/tests/images/closed.gif b/includes/js/dojox/grid/tests/images/closed.gif
new file mode 100644
index 0000000..7d3afa4
--- /dev/null
+++ b/includes/js/dojox/grid/tests/images/closed.gif
Binary files differ
diff --git a/includes/js/dojox/grid/tests/images/flatScreen.gif b/includes/js/dojox/grid/tests/images/flatScreen.gif
new file mode 100644
index 0000000..05edd72
--- /dev/null
+++ b/includes/js/dojox/grid/tests/images/flatScreen.gif
Binary files differ
diff --git a/includes/js/dojox/grid/tests/images/open.gif b/includes/js/dojox/grid/tests/images/open.gif
new file mode 100644
index 0000000..37efd2c
--- /dev/null
+++ b/includes/js/dojox/grid/tests/images/open.gif
Binary files differ
diff --git a/includes/js/dojox/grid/tests/support/books.xml b/includes/js/dojox/grid/tests/support/books.xml
new file mode 100644
index 0000000..4c330e6
--- /dev/null
+++ b/includes/js/dojox/grid/tests/support/books.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<books>
+ <book>
+ <isbn>1</isbn>
+ <title>Title of 1</title>
+ <author>Author of 1</author>
+ </book>
+ <book>
+ <isbn>2</isbn>
+ <title>Title of 2</title>
+ <author>Author of 2</author>
+ </book>
+ <book>
+ <isbn>3</isbn>
+ <title>Title of 3</title>
+ <author>Author of 3</author>
+ </book>
+ <book>
+ <isbn>4</isbn>
+ <title>Title of 4</title>
+ <author>Author of 4</author>
+ </book>
+ <book>
+ <isbn>5</isbn>
+ <title>Title of 5</title>
+ <author>Author of 5</author>
+ </book>
+ <book>
+ <isbn>6</isbn>
+ <title>Title of 6</title>
+ <author>Author of 6</author>
+ </book>
+ <book>
+ <isbn>7</isbn>
+ <title>Title of 7</title>
+ <author>Author of 7</author>
+ </book>
+ <book>
+ <isbn>8</isbn>
+ <title>Title of 8</title>
+ <author>Author of 8</author>
+ </book>
+ <book>
+ <isbn>9</isbn>
+ <title>Title of 9</title>
+ <author>Author of 9</author>
+ </book>
+ <book>
+ <isbn>10</isbn>
+ <title>Title of 10</title>
+ <author>Author of 10</author>
+ </book>
+ <book>
+ <isbn>11</isbn>
+ <title>Title of 11</title>
+ <author>Author of 11</author>
+ </book>
+ <book>
+ <isbn>12</isbn>
+ <title>Title of 12</title>
+ <author>Author of 12</author>
+ </book>
+ <book>
+ <isbn>13</isbn>
+ <title>Title of 13</title>
+ <author>Author of 13</author>
+ </book>
+ <book>
+ <isbn>14</isbn>
+ <title>Title of 14</title>
+ <author>Author of 14</author>
+ </book>
+ <book>
+ <isbn>15</isbn>
+ <title>Title of 15</title>
+ <author>Author of 15</author>
+ </book>
+ <book>
+ <isbn>16</isbn>
+ <title>Title of 16</title>
+ <author>Author of 16</author>
+ </book>
+ <book>
+ <isbn>17</isbn>
+ <title>Title of 17</title>
+ <author>Author of 17</author>
+ </book>
+ <book>
+ <isbn>18</isbn>
+ <title>Title of 18</title>
+ <author>Author of 18</author>
+ </book>
+ <book>
+ <isbn>19</isbn>
+ <title>Title of 19</title>
+ <author>Author of 19</author>
+ </book>
+ <book>
+ <isbn>20</isbn>
+ <title>Title of 20</title>
+ <author>Author of 20</author>
+ </book>
+</books>
diff --git a/includes/js/dojox/grid/tests/support/data.php b/includes/js/dojox/grid/tests/support/data.php
new file mode 100644
index 0000000..1beb6f0
--- /dev/null
+++ b/includes/js/dojox/grid/tests/support/data.php
@@ -0,0 +1,379 @@
+<?php
+ // db settings
+ $dbserver = 'localhost';
+ $dbuser = 'root';
+ $dbpassword = 'root';
+
+ error_reporting(E_ALL);
+
+ /*
+ Simple protocol:
+ - Inputs via POST variables.
+ - Output is a string that can be evaluated into a JSON
+ First element of the array contains return status.
+
+ This simplified tutorial code should not be deployed without a security review.
+ */
+
+ @include "json.php";
+
+ // set up response encoding
+ header("Content-Type: text/html; charset=utf-8");
+
+ // util
+ function getPostString($inName) {
+ // make sure input strings are 'clean'
+ return mysql_real_escape_string(@$_POST[$inName]);
+ }
+
+ // used for json encoding
+ $json = new Services_JSON();
+
+ function echoJson($inData) {
+ global $json;
+ // delay in ms
+ $delay = getPostString('delay');
+ if (!empty($delay))
+ usleep($delay * 1000);
+ echo '/* ' . $json->encode($inData) . ' */';
+ }
+
+ function error($inMessage) {
+ $inMessage = str_replace('"', '\\"', $inMessage);
+ error_log($inMessage);
+ //echo '/* ({error: true, message: "' . $inMessage . '"}) */';
+ echoJson(array('error' => true, 'message' => $inMessage));
+ exit;
+ }
+
+
+ function getArray($inResult, $inArray="true") {
+ $o = Array();
+ while ($row = ($inArray ? mysql_fetch_row($inResult) : mysql_fetch_object($inResult)))
+ $o[] = $row;
+ return $o;
+ }
+
+ // connect to DB
+ mysql_connect($dbserver, $dbuser, $dbpassword);
+
+ // select DB
+ $database = getPostString("database");
+ $database = ($database ? $database : $db);
+ if (!mysql_select_db($database))
+ error('failed to select db: ' . mysql_error());
+
+ // select table
+ $table = getPostString("table");
+ $table = ($table ? $table : $dbtable);
+
+ // cache
+ $colCache = NULL;
+ $pkCache = NULL;
+
+ // set UTF8 output (MySql > 4.0)
+ mysql_query("SET NAMES UTF8");
+
+ // server, database, table meta data
+ function getDatabases() {
+ $result = mysql_query("SHOW DATABASES");
+ $output = Array();
+ while ($row = mysql_fetch_row($result)) {
+ $r = strtolower($row[0]);
+ if ($r != 'mysql' && $r != 'information_schema')
+ $output[] = $row[0];
+ }
+ return $output;
+ }
+
+ function getTables() {
+ global $database;
+ $result = mysql_query("SHOW TABLES FROM $database");
+ $output = Array();
+ while ($row = mysql_fetch_row($result))
+ $output[] = $row[0];
+ return $output;
+ }
+
+ function getColumns() {
+ global $table, $colCache;
+ if (!$colCache) {
+ $result = mysql_query("SHOW COLUMNS FROM `$table`");
+ return getArray($result, false);
+ $colCache = getArray($result, false);
+ }
+ return $colCache;
+ }
+
+ // returns object: $this->name, $this->index
+ function getPk() {
+ global $pkCache;
+ if (!$pkCache) {
+ $k = '';
+ $columns = getColumns();
+ for ($i=0; $i < count($columns); $i++) {
+ $c = $columns[$i];
+ if ($c->Key == 'PRI') {
+ $k = $c->Field;
+ break;
+ }
+ }
+ $pkCache->index = $i;
+ $pkCache->name = $k;
+ }
+ return $pkCache;
+ }
+
+ function getTableInfo() {
+ global $table, $database;
+ $c = getColumns();
+ $r = rowcount();
+ return array("count" => $r, "columns" => $c, "database" => $database, "table" => $table);
+ }
+
+ function getOldPostPkValue() {
+ $pk = getPk();
+ return getPostString('_o' . $pk->index);
+ }
+
+ function getNewPostPkValue() {
+ $pk = getPk();
+ return getPostString('_' . $pk->index);
+ }
+
+ function getPostColumns() {
+ $columns = getColumns();
+ for ($i=0, $a=array(), $p; (($p=getPostString("_".$i)) != ''); $i++) {
+ $r = new stdClass();
+ $r->name = $columns[$i]->Field;
+ $r->value = $p;
+ $a[] = $r;
+ }
+ return $a;
+ }
+
+ function getOrderBy() {
+ $ob = getPostString("orderby");
+ if (is_numeric($ob)) {
+ $columns = getColumns();
+ $ob = $columns[intval($ob)-1]->Field;
+ }
+ return $ob;
+ }
+
+ function getWhere() {
+ $w = getPostString("where");
+ return ($w ? " WHERE $w" : "");
+ }
+
+ // basic operations
+ function rowcount() {
+ global $table;
+ $query = "SELECT COUNT(*) FROM `$table`" . getWhere();
+ $result = mysql_query($query);
+ if (!$result)
+ error("failed to perform query: $query. " . mysql_error());
+ if ($row = mysql_fetch_row($result))
+ return $row[0];
+ else
+ return 0;
+ }
+
+ function select($inQuery = '') {
+ global $table;
+ // built limit clause
+ $lim = (int)getPostString("limit");
+ $off = (int)getPostString("offset");
+ $limit = ($lim || $off ? " LIMIT $off, $lim" : "");
+ // build order by clause
+ $desc = (boolean)getPostString("desc");
+ $ob = getOrderBy();
+ $orderby = ($ob ? " ORDER BY `" . $ob . "`" . ($desc ? " DESC" : "") : "");
+ // build query
+ $query = ($inQuery ? $inQuery : "SELECT * FROM `$table`" . getWhere() . $orderby . $limit);
+ // execute query
+ if (!$result = mysql_query($query))
+ error("failed to perform query: $query. " . mysql_error());
+ // fetch each result row
+ return getArray($result);
+ }
+
+ function reflectRow() {
+ global $table;
+ $pk = getPk();
+ $key = getNewPostPkValue();
+ $where = "`$pk->name`=\"$key\"";
+ return select("SELECT * FROM `$table` WHERE $where LIMIT 1");
+ }
+
+ function update() {
+ // build set clause
+ for ($i=0, $set = array(), $cols = getPostColumns(), $v; ($v=$cols[$i]); $i++)
+ $set[] = "`$v->name` = '$v->value'";
+ $set = implode(', ', $set);
+ // our table
+ global $table;
+ // build query
+ $pk = getPk();
+ $pkValue = getOldPostPkValue();
+ $query = "UPDATE `$table` SET $set WHERE `$pk->name` = '$pkValue' LIMIT 1";
+ // execute query
+ if (!mysql_query($query))
+ error("failed to perform query: [$query]. " .
+ "MySql says: [" . mysql_error() ."]");
+ else {
+ return reflectRow();
+ }
+ }
+
+ function insert() {
+ global $table;
+ // build values clause
+ for ($i=0, $values = array(), $cols = getPostColumns(), $v; ($v=$cols[$i]); $i++)
+ $values[] = $v->value;
+ $values = '"' . implode('", "', $values) . '"';
+ // build query
+ $query = "INSERT INTO `$table` VALUES($values)";
+ // execute query
+ if (!mysql_query($query))
+ error("failed to perform query: [$query]. " .
+ "MySql says: [" . mysql_error() ."]");
+ else {
+ return reflectRow();
+ }
+ }
+
+ function delete() {
+ global $table;
+ // build query
+ $n = getPostString("count");
+ $pk = getPk();
+ for ($i = 0, $deleted=array(); $i < $n; $i++) {
+ $key = getPostString("_$i");
+ array_push($deleted, $key);
+ $query = "DELETE FROM `$table` WHERE `$pk->name`=\"$key\" LIMIT 1";
+ // execute query
+ if (!mysql_query($query) || mysql_affected_rows() != 1)
+ error("failed to perform query: [$query]. " .
+ "Affected rows: " . mysql_affected_rows() .". " .
+ "MySql says: [" . mysql_error() ."]");
+ }
+ return $deleted;
+ }
+
+ // find (full text search)
+ function findData($inFindCol, $inFind, $inOrderBy, $inFullText) {
+ global $table;
+ $where = ($inFullText ? "WHERE MATCH(`$inFindCol`) AGAINST ('$inFind')" : "WHERE $inFindCol LIKE '$inFind'");
+ $query = "SELECT * FROM $table $where $inOrderBy";
+ $result = mysql_query($query);
+ // return rows
+ return getArray($result);
+ }
+
+ // binary search through sorted data, supports start point ($inFindFrom) and direction ($inFindForward)
+ function findRow($inData, $inFindFrom=-1, $inFindForward) {
+ $b = -1;
+ $l = count($inData);
+ if (!$inData)
+ return $b;
+ if (!$inFindFrom==-1 || $l < 2)
+ $b = 0;
+ else {
+ // binary search
+ $t = $l-1;
+ $b = 0;
+ while ($b <= $t) {
+ $p = floor(($b+$t)/2);
+ $d = $inData[$p][0];
+ if ($d < $inFindFrom)
+ $b = $p + 1;
+ else if ($d > $inFindFrom)
+ $t = $p - 1;
+ else {
+ $b = $p;
+ break;
+ }
+ }
+ if ($inFindFrom == $inData[$b][0]) {
+ // add or subtract 1
+ $b = ($inFindForward ? ($b+1 > $l-1 ? 0 : $b+1) : ($b-1 < 0 ? $l-1 : $b-1) );
+ }
+ else if (!$inFindForward)
+ // subtract 1
+ $b = ($b-1 < 0 ? $l-1 : $b-1);
+ }
+ return $inData[$b][0];
+ }
+
+ function buildFindWhere($inFindData, $inKey, $inCol) {
+ $o = Array();
+ foreach($inFindData as $row)
+ $o[] = $inCol . "='" . $row[$inKey] . "'";
+ return (count($o) ? ' WHERE ' . implode(' OR ', $o) : '');
+ }
+
+ function find($inFindCol, $inFind='', $inOb='', $inFindFrom=0, $inFindForward=true, $inFullText=true) {
+ global $table;
+ // build order by clause
+ $desc = (boolean)getPostString("desc");
+ if (!$inOb)
+ $inOb = getOrderBy();
+ if ($inOb)
+ $inOb = "`" . $inOb . "`" ;
+ $orderby = ($inOb ? " ORDER BY $inOb " . ($desc ? " DESC" : "") : "");
+ // update inputs from post
+ if (!$inFind)
+ $inFind = getPostString('findText');
+ if (!$inFindCol)
+ $inFindCol = getPostString('findCol');
+ if (empty($inFindFrom))
+ $inFindFrom = getPostString('findFrom');
+ $ff = getPostString('findForward');
+ if ($ff)
+ $inFindForward = (strtolower($ff) == 'true' ? true : false);
+ $ft = getPostString('findFullText');
+ if ($ft)
+ $inFullText = (strtolower($ft) == 'true' ? true : false);
+
+ // get find data
+ $f = findData($inFindCol, $inFind, $orderby, $inFullText);
+ $pk = getPk();
+
+ // execute query
+ $where = buildFindWhere($f, $pk->index, 'f');
+ $query = "SELECT Row, f FROM (SELECT @row := @row + 1 AS Row, $pk->name as f FROM `$table` $orderby) AS tempTable $where";
+ mysql_query('SET @row = -1;');
+ if (!$result = mysql_query($query))
+ error("failed to perform query: $query. " . mysql_error());
+
+ // return row number
+ return findRow(getArray($result), $inFindFrom, $inFindForward);
+ }
+
+ // our command list
+ $cmds = array(
+ "count" => "rowcount",
+ "select" => "select",
+ "update" => "update",
+ "insert" => "insert",
+ "delete" => "delete",
+ "find" => "find",
+ "databases" => "getDatabases",
+ "tables" => "getTables",
+ "columns" => "getColumns",
+ "info" => "getTableInfo"
+ );
+
+ // process input params
+ $cmd = @$_POST["command"];
+
+ //$cmd="select";
+
+ // dispatch command
+ $func = @$cmds[$cmd];
+ if (function_exists($func))
+ echoJson(call_user_func($func));
+ else
+ error("bad command");
+?>
diff --git a/includes/js/dojox/grid/tests/support/geography.xml b/includes/js/dojox/grid/tests/support/geography.xml
new file mode 100644
index 0000000..070a8c1
--- /dev/null
+++ b/includes/js/dojox/grid/tests/support/geography.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<opml version="1.0">
+ <head>
+ <title>geography.opml</title>
+ <dateCreated>2006-11-10</dateCreated>
+ <dateModified>2006-11-13</dateModified>
+ <ownerName>Magellan, Ferdinand</ownerName>
+ </head>
+ <body>
+ <outline text="Africa" type="continent">
+ <outline text="Egypt" type="country"/>
+ <outline text="Kenya" type="country">
+ <outline text="Nairobi" type="city"/>
+ <outline text="Mombasa" type="city"/>
+ </outline>
+ <outline text="Sudan" type="country">
+ <outline text="Khartoum" type="city"/>
+ </outline>
+ </outline>
+ <outline text="Asia" type="continent">
+ <outline text="China" type="country"/>
+ <outline text="India" type="country"/>
+ <outline text="Russia" type="country"/>
+ <outline text="Mongolia" type="country"/>
+ </outline>
+ <outline text="Australia" type="continent" population="21 million">
+ <outline text="Australia" type="country" population="21 million"/>
+ </outline>
+ <outline text="Europe" type="continent">
+ <outline text="Germany" type="country"/>
+ <outline text="France" type="country"/>
+ <outline text="Spain" type="country"/>
+ <outline text="Italy" type="country"/>
+ </outline>
+ <outline text="North America" type="continent">
+ <outline text="Mexico" type="country" population="108 million" area="1,972,550 sq km">
+ <outline text="Mexico City" type="city" population="19 million" timezone="-6 UTC"/>
+ <outline text="Guadalajara" type="city" population="4 million" timezone="-6 UTC"/>
+ </outline>
+ <outline text="Canada" type="country" population="33 million" area="9,984,670 sq km">
+ <outline text="Ottawa" type="city" population="0.9 million" timezone="-5 UTC"/>
+ <outline text="Toronto" type="city" population="2.5 million" timezone="-5 UTC"/>
+ </outline>
+ <outline text="United States of America" type="country"/>
+ </outline>
+ <outline text="South America" type="continent">
+ <outline text="Brazil" type="country" population="186 million"/>
+ <outline text="Argentina" type="country" population="40 million"/>
+ </outline>
+ </body>
+</opml>
diff --git a/includes/js/dojox/grid/tests/support/json.php b/includes/js/dojox/grid/tests/support/json.php
new file mode 100644
index 0000000..84e3dfa
--- /dev/null
+++ b/includes/js/dojox/grid/tests/support/json.php
@@ -0,0 +1,794 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+* Converts to and from JSON format.
+*
+* JSON (JavaScript Object Notation) is a lightweight data-interchange
+* format. It is easy for humans to read and write. It is easy for machines
+* to parse and generate. It is based on a subset of the JavaScript
+* Programming Language, Standard ECMA-262 3rd Edition - December 1999.
+* This feature can also be found in Python. JSON is a text format that is
+* completely language independent but uses conventions that are familiar
+* to programmers of the C-family of languages, including C, C++, C#, Java,
+* JavaScript, Perl, TCL, and many others. These properties make JSON an
+* ideal data-interchange language.
+*
+* This package provides a simple encoder and decoder for JSON notation. It
+* is intended for use with client-side Javascript applications that make
+* use of HTTPRequest to perform server communication functions - data can
+* be encoded into JSON notation for use in a client-side javascript, or
+* decoded from incoming Javascript requests. JSON format is native to
+* Javascript, and can be directly eval()'ed with no further parsing
+* overhead
+*
+* All strings should be in ASCII or UTF-8 format!
+*
+* LICENSE: Redistribution and use in source and binary forms, with or
+* without modification, are permitted provided that the following
+* conditions are met: Redistributions of source code must retain the
+* above copyright notice, this list of conditions and the following
+* disclaimer. Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following disclaimer
+* in the documentation and/or other materials provided with the
+* distribution.
+*
+* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+* NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+* DAMAGE.
+*
+* @category
+* @package Services_JSON
+* @author Michal Migurski <mike-json@teczno.com>
+* @author Matt Knapp <mdknapp[at]gmail[dot]com>
+* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+* @copyright 2005 Michal Migurski
+* @license http://www.opensource.org/licenses/bsd-license.php
+* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+*/
+
+/**
+* Marker constant for Services_JSON::decode(), used to flag stack state
+*/
+define('SERVICES_JSON_SLICE', 1);
+
+/**
+* Marker constant for Services_JSON::decode(), used to flag stack state
+*/
+define('SERVICES_JSON_IN_STR', 2);
+
+/**
+* Marker constant for Services_JSON::decode(), used to flag stack state
+*/
+define('SERVICES_JSON_IN_ARR', 4);
+
+/**
+* Marker constant for Services_JSON::decode(), used to flag stack state
+*/
+define('SERVICES_JSON_IN_OBJ', 8);
+
+/**
+* Marker constant for Services_JSON::decode(), used to flag stack state
+*/
+define('SERVICES_JSON_IN_CMT', 16);
+
+/**
+* Behavior switch for Services_JSON::decode()
+*/
+define('SERVICES_JSON_LOOSE_TYPE', 10);
+
+/**
+* Behavior switch for Services_JSON::decode()
+*/
+define('SERVICES_JSON_STRICT_TYPE', 11);
+
+/**
+* Encodings
+*/
+define('SERVICES_JSON_ISO_8859_1', 'iso-8859-1');
+define('SERVICES_JSON_UTF_8', 'utf-8');
+
+/**
+* Converts to and from JSON format.
+*
+* Brief example of use:
+*
+* <code>
+* // create a new instance of Services_JSON
+* $json = new Services_JSON();
+*
+* // convert a complexe value to JSON notation, and send it to the browser
+* $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
+* $output = $json->encode($value);
+*
+* print($output);
+* // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
+*
+* // accept incoming POST data, assumed to be in JSON notation
+* $input = file_get_contents('php://input', 1000000);
+* $value = $json->decode($input);
+* </code>
+*/
+class Services_JSON
+{
+ /**
+ * constructs a new JSON instance
+ *
+ //>> SJM2005
+ * @param string $encoding Strings are input/output in this encoding
+ * @param int $encode Encode input is expected in this character encoding
+ //<< SJM2005
+ *
+ * @param int $use object behavior: when encoding or decoding,
+ * be loose or strict about object/array usage
+ *
+ * possible values:
+ * - SERVICES_JSON_STRICT_TYPE: strict typing, default.
+ * "{...}" syntax creates objects in decode().
+ * - SERVICES_JSON_LOOSE_TYPE: loose typing.
+ * "{...}" syntax creates associative arrays in decode().
+ */
+ function Services_JSON($encoding = SERVICES_JSON_UTF_8, $use = SERVICES_JSON_STRICT_TYPE)
+ {
+ //>> SJM2005
+ $this->encoding = $encoding;
+ //<< SJM2005
+
+ $this->use = $use;
+ }
+
+ /**
+ * convert a string from one UTF-16 char to one UTF-8 char
+ *
+ * Normally should be handled by mb_convert_encoding, but
+ * provides a slower PHP-only method for installations
+ * that lack the multibye string extension.
+ *
+ * @param string $utf16 UTF-16 character
+ * @return string UTF-8 character
+ * @access private
+ */
+ function utf162utf8($utf16)
+ {
+ // oh please oh please oh please oh please oh please
+ if(function_exists('mb_convert_encoding'))
+ return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
+
+ $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
+
+ switch(true) {
+ case ((0x7F & $bytes) == $bytes):
+ // this case should never be reached, because we are in ASCII range
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ return chr(0x7F & $bytes);
+
+ case (0x07FF & $bytes) == $bytes:
+ // return a 2-byte UTF-8 character
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ return chr(0xC0 | (($bytes >> 6) & 0x1F))
+ . chr(0x80 | ($bytes & 0x3F));
+
+ case (0xFFFF & $bytes) == $bytes:
+ // return a 3-byte UTF-8 character
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ return chr(0xE0 | (($bytes >> 12) & 0x0F))
+ . chr(0x80 | (($bytes >> 6) & 0x3F))
+ . chr(0x80 | ($bytes & 0x3F));
+ }
+
+ // ignoring UTF-32 for now, sorry
+ return '';
+ }
+
+ /**
+ * convert a string from one UTF-8 char to one UTF-16 char
+ *
+ * Normally should be handled by mb_convert_encoding, but
+ * provides a slower PHP-only method for installations
+ * that lack the multibye string extension.
+ *
+ * @param string $utf8 UTF-8 character
+ * @return string UTF-16 character
+ * @access private
+ */
+ function utf82utf16($utf8)
+ {
+ // oh please oh please oh please oh please oh please
+ if(function_exists('mb_convert_encoding'))
+ return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
+
+ switch(strlen($utf8)) {
+ case 1:
+ // this case should never be reached, because we are in ASCII range
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ return $utf8;
+
+ case 2:
+ // return a UTF-16 character from a 2-byte UTF-8 char
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ return chr(0x07 & (ord($utf8{0}) >> 2))
+ . chr((0xC0 & (ord($utf8{0}) << 6))
+ | (0x3F & ord($utf8{1})));
+
+ case 3:
+ // return a UTF-16 character from a 3-byte UTF-8 char
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ return chr((0xF0 & (ord($utf8{0}) << 4))
+ | (0x0F & (ord($utf8{1}) >> 2)))
+ . chr((0xC0 & (ord($utf8{1}) << 6))
+ | (0x7F & ord($utf8{2})));
+ }
+
+ // ignoring UTF-32 for now, sorry
+ return '';
+ }
+
+ /**
+ * encodes an arbitrary variable into JSON format
+ *
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
+ * see argument 1 to Services_JSON() above for array-parsing behavior.
+ * if var is a strng, note that encode() always expects it
+ * to be in ASCII or UTF-8 format!
+ *
+ * @return string JSON string representation of input var
+ * @access public
+ */
+ function encode($var)
+ {
+ switch (gettype($var)) {
+ case 'boolean':
+ return $var ? 'true' : 'false';
+
+ case 'NULL':
+ return 'null';
+
+ case 'integer':
+ return (int) $var;
+
+ case 'double':
+ case 'float':
+ return (float) $var;
+
+ case 'string':
+ //>> SJM2005
+ if ($this->encoding == SERVICES_JSON_UTF_8)
+ ;
+ else if ($this->encoding == SERVICES_JSON_ISO_8859_1)
+ $var = utf8_encode($var);
+ else if (!function_exists('mb_convert_encoding'))
+ die('Requested encoding requires mb_strings extension.');
+ else
+ $var = mb_convert_encoding($var, "utf-8", $this->encoding);
+ //<< SJM2005
+
+ // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+ $ascii = '';
+ $strlen_var = strlen($var);
+
+ /*
+ * Iterate over every character in the string,
+ * escaping with a slash or encoding to UTF-8 where necessary
+ */
+ for ($c = 0; $c < $strlen_var; ++$c) {
+
+ $ord_var_c = ord($var{$c});
+
+ switch (true) {
+ case $ord_var_c == 0x08:
+ $ascii .= '\b';
+ break;
+ case $ord_var_c == 0x09:
+ $ascii .= '\t';
+ break;
+ case $ord_var_c == 0x0A:
+ $ascii .= '\n';
+ break;
+ case $ord_var_c == 0x0C:
+ $ascii .= '\f';
+ break;
+ case $ord_var_c == 0x0D:
+ $ascii .= '\r';
+ break;
+
+ case $ord_var_c == 0x22:
+ case $ord_var_c == 0x2F:
+ case $ord_var_c == 0x5C:
+ // double quote, slash, slosh
+ $ascii .= '\\'.$var{$c};
+ break;
+
+ case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+ // characters U-00000000 - U-0000007F (same as ASCII)
+ $ascii .= $var{$c};
+ break;
+
+ case (($ord_var_c & 0xE0) == 0xC0):
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
+ $c += 1;
+ $utf16 = $this->utf82utf16($char);
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+
+ case (($ord_var_c & 0xF0) == 0xE0):
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c,
+ ord($var{$c + 1}),
+ ord($var{$c + 2}));
+ $c += 2;
+ $utf16 = $this->utf82utf16($char);
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+
+ case (($ord_var_c & 0xF8) == 0xF0):
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c,
+ ord($var{$c + 1}),
+ ord($var{$c + 2}),
+ ord($var{$c + 3}));
+ $c += 3;
+ $utf16 = $this->utf82utf16($char);
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+
+ case (($ord_var_c & 0xFC) == 0xF8):
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c,
+ ord($var{$c + 1}),
+ ord($var{$c + 2}),
+ ord($var{$c + 3}),
+ ord($var{$c + 4}));
+ $c += 4;
+ $utf16 = $this->utf82utf16($char);
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+
+ case (($ord_var_c & 0xFE) == 0xFC):
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c,
+ ord($var{$c + 1}),
+ ord($var{$c + 2}),
+ ord($var{$c + 3}),
+ ord($var{$c + 4}),
+ ord($var{$c + 5}));
+ $c += 5;
+ $utf16 = $this->utf82utf16($char);
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+ }
+ }
+
+ return '"'.$ascii.'"';
+
+ case 'array':
+ /*
+ * As per JSON spec if any array key is not an integer
+ * we must treat the the whole array as an object. We
+ * also try to catch a sparsely populated associative
+ * array with numeric keys here because some JS engines
+ * will create an array with empty indexes up to
+ * max_index which can cause memory issues and because
+ * the keys, which may be relevant, will be remapped
+ * otherwise.
+ *
+ * As per the ECMA and JSON specification an object may
+ * have any string as a property. Unfortunately due to
+ * a hole in the ECMA specification if the key is a
+ * ECMA reserved word or starts with a digit the
+ * parameter is only accessible using ECMAScript's
+ * bracket notation.
+ */
+
+ // treat as a JSON object
+ if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+ return '{' .
+ join(',', array_map(array($this, 'name_value'),
+ array_keys($var),
+ array_values($var)))
+ . '}';
+ }
+
+ // treat it like a regular array
+ return '[' . join(',', array_map(array($this, 'encode'), $var)) . ']';
+
+ case 'object':
+ $vars = get_object_vars($var);
+ return '{' .
+ join(',', array_map(array($this, 'name_value'),
+ array_keys($vars),
+ array_values($vars)))
+ . '}';
+
+ default:
+ return '';
+ }
+ }
+
+ /**
+ * array-walking function for use in generating JSON-formatted name-value pairs
+ *
+ * @param string $name name of key to use
+ * @param mixed $value reference to an array element to be encoded
+ *
+ * @return string JSON-formatted name-value pair, like '"name":value'
+ * @access private
+ */
+ function name_value($name, $value)
+ {
+ return $this->encode(strval($name)) . ':' . $this->encode($value);
+ }
+
+ /**
+ * reduce a string by removing leading and trailing comments and whitespace
+ *
+ * @param $str string string value to strip of comments and whitespace
+ *
+ * @return string string value stripped of comments and whitespace
+ * @access private
+ */
+ function reduce_string($str)
+ {
+ $str = preg_replace(array(
+
+ // eliminate single line comments in '// ...' form
+ '#^\s*//(.+)$#m',
+
+ // eliminate multi-line comments in '/* ... */' form, at start of string
+ '#^\s*/\*(.+)\*/#Us',
+
+ // eliminate multi-line comments in '/* ... */' form, at end of string
+ '#/\*(.+)\*/\s*$#Us'
+
+ ), '', $str);
+
+ // eliminate extraneous space
+ return trim($str);
+ }
+
+ /**
+ * decodes a JSON string into appropriate variable
+ *
+ * @param string $str JSON-formatted string
+ *
+ * @return mixed number, boolean, string, array, or object
+ * corresponding to given JSON input string.
+ * See argument 1 to Services_JSON() above for object-output behavior.
+ * Note that decode() always returns strings
+ * in ASCII or UTF-8 format!
+ * @access public
+ */
+ function decode($str)
+ {
+ $str = $this->reduce_string($str);
+
+ switch (strtolower($str)) {
+ case 'true':
+ return true;
+
+ case 'false':
+ return false;
+
+ case 'null':
+ return null;
+
+ default:
+ if (is_numeric($str)) {
+ // Lookie-loo, it's a number
+
+ // This would work on its own, but I'm trying to be
+ // good about returning integers where appropriate:
+ // return (float)$str;
+
+ // Return float or int, as appropriate
+ return ((float)$str == (integer)$str)
+ ? (integer)$str
+ : (float)$str;
+
+ } elseif (preg_match('/^("|\').+(\1)$/s', $str, $m) && $m[1] == $m[2]) {
+ // STRINGS RETURNED IN UTF-8 FORMAT
+ $delim = substr($str, 0, 1);
+ $chrs = substr($str, 1, -1);
+ $utf8 = '';
+ $strlen_chrs = strlen($chrs);
+
+ for ($c = 0; $c < $strlen_chrs; ++$c) {
+
+ $substr_chrs_c_2 = substr($chrs, $c, 2);
+ $ord_chrs_c = ord($chrs{$c});
+
+ switch (true) {
+ case $substr_chrs_c_2 == '\b':
+ $utf8 .= chr(0x08);
+ ++$c;
+ break;
+ case $substr_chrs_c_2 == '\t':
+ $utf8 .= chr(0x09);
+ ++$c;
+ break;
+ case $substr_chrs_c_2 == '\n':
+ $utf8 .= chr(0x0A);
+ ++$c;
+ break;
+ case $substr_chrs_c_2 == '\f':
+ $utf8 .= chr(0x0C);
+ ++$c;
+ break;
+ case $substr_chrs_c_2 == '\r':
+ $utf8 .= chr(0x0D);
+ ++$c;
+ break;
+
+ case $substr_chrs_c_2 == '\\"':
+ case $substr_chrs_c_2 == '\\\'':
+ case $substr_chrs_c_2 == '\\\\':
+ case $substr_chrs_c_2 == '\\/':
+ if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
+ ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
+ $utf8 .= $chrs{++$c};
+ }
+ break;
+
+ case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
+ //echo ' matching single escaped unicode character from ' . substr($chrs, $c, 6);
+ // single, escaped unicode character
+ $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
+ . chr(hexdec(substr($chrs, ($c + 4), 2)));
+ $utf8 .= $this->utf162utf8($utf16);
+ $c += 5;
+ break;
+
+ case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
+ $utf8 .= $chrs{$c};
+ break;
+
+ case ($ord_chrs_c & 0xE0) == 0xC0:
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
+ //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 2);
+ ++$c;
+ break;
+
+ case ($ord_chrs_c & 0xF0) == 0xE0:
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 3);
+ $c += 2;
+ break;
+
+ case ($ord_chrs_c & 0xF8) == 0xF0:
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 4);
+ $c += 3;
+ break;
+
+ case ($ord_chrs_c & 0xFC) == 0xF8:
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 5);
+ $c += 4;
+ break;
+
+ case ($ord_chrs_c & 0xFE) == 0xFC:
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 6);
+ $c += 5;
+ break;
+
+ }
+
+ }
+
+ //>> SJM2005
+ if ($this->encoding == SERVICES_JSON_UTF_8)
+ return $utf8;
+ if ($this->encoding == SERVICES_JSON_ISO_8859_1)
+ return utf8_decode($utf8);
+ else if (!function_exists('mb_convert_encoding'))
+ die('Requested encoding requires mb_strings extension.');
+ else
+ return mb_convert_encoding($utf8, $this->encoding, SERVICES_JSON_UTF_8);
+ //<< SJM2005
+
+ return $utf8;
+
+ } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
+ // array, or object notation
+ if ($str{0} == '[') {
+ $stk = array(SERVICES_JSON_IN_ARR);
+ $arr = array();
+ } else {
+ if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+ $stk = array(SERVICES_JSON_IN_OBJ);
+ $obj = array();
+ } else {
+ $stk = array(SERVICES_JSON_IN_OBJ);
+ $obj = new stdClass();
+ }
+ }
+
+ array_push($stk, array('what' => SERVICES_JSON_SLICE,
+ 'where' => 0,
+ 'delim' => false));
+
+ $chrs = substr($str, 1, -1);
+ $chrs = $this->reduce_string($chrs);
+
+ if ($chrs == '') {
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
+ return $arr;
+
+ } else {
+ return $obj;
+
+ }
+ }
+
+ //print("\nparsing {$chrs}\n");
+
+ $strlen_chrs = strlen($chrs);
+ for ($c = 0; $c <= $strlen_chrs; ++$c) {
+
+ $top = end($stk);
+ $substr_chrs_c_2 = substr($chrs, $c, 2);
+
+ if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
+ // found a comma that is not inside a string, array, etc.,
+ // OR we've reached the end of the character list
+ $slice = substr($chrs, $top['where'], ($c - $top['where']));
+ array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
+ //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
+ // we are in an array, so just push an element onto the stack
+ array_push($arr, $this->decode($slice));
+
+ } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+ // we are in an object, so figure
+ // out the property name and set an
+ // element in an associative array,
+ // for now
+ if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+ // "name":value pair
+ $key = $this->decode($parts[1]);
+ $val = $this->decode($parts[2]);
+
+ if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+ $obj[$key] = $val;
+ } else {
+ $obj->$key = $val;
+ }
+ } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+ // name:value pair, where name is unquoted
+ $key = $parts[1];
+ $val = $this->decode($parts[2]);
+
+ if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+ $obj[$key] = $val;
+ } else {
+ $obj->$key = $val;
+ }
+ }
+
+ }
+
+ } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
+ // found a quote, and we are not inside a string
+ array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
+ //print("Found start of string at {$c}\n");
+
+ //>> SAO2006
+ /*} elseif (($chrs{$c} == $top['delim']) &&
+ ($top['what'] == SERVICES_JSON_IN_STR) &&
+ (($chrs{$c - 1} != '\\') ||
+ ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) {*/
+ } elseif ($chrs{$c} == $top['delim'] &&
+ $top['what'] == SERVICES_JSON_IN_STR) {
+ //print("Found potential end of string at {$c}\n");
+ // verify quote is not escaped: it has no or an even number of \\ before it.
+ for ($i=0; ($chrs{$c - ($i+1)} == '\\'); $i++);
+ /*$i = 0;
+ while ( $chrs{$c - ($i+1)} == '\\')
+ $i++;*/
+ //print("Found {$i} \ before delim\n");
+ if ($i % 2 != 0)
+ {
+ //print("delim escaped, not end of string\n");
+ continue;
+ }
+ //>> SAO2006
+ // found a quote, we're in a string, and it's not escaped
+ array_pop($stk);
+ //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
+
+ } elseif (($chrs{$c} == '[') &&
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+ // found a left-bracket, and we are in an array, object, or slice
+ array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
+ //print("Found start of array at {$c}\n");
+
+ } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
+ // found a right-bracket, and we're in an array
+ array_pop($stk);
+ //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+ } elseif (($chrs{$c} == '{') &&
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+ // found a left-brace, and we are in an array, object, or slice
+ array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
+ //print("Found start of object at {$c}\n");
+
+ } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
+ // found a right-brace, and we're in an object
+ array_pop($stk);
+ //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+ } elseif (($substr_chrs_c_2 == '/*') &&
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+ // found a comment start, and we are in an array, object, or slice
+ array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
+ $c++;
+ //print("Found start of comment at {$c}\n");
+
+ } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
+ // found a comment end, and we're in one now
+ array_pop($stk);
+ $c++;
+
+ for ($i = $top['where']; $i <= $c; ++$i)
+ $chrs = substr_replace($chrs, ' ', $i, 1);
+
+ //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+ }
+
+ }
+
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
+ return $arr;
+
+ } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+ return $obj;
+
+ }
+
+ }
+ }
+ }
+
+}
+
+ /*function hex($s)
+ {
+ $l = strlen($s);
+ for ($i=0; $i < $l; $i++)
+ //echo '['.(ord($s{$i})).']';
+ echo '['.bin2hex($s{$i}).']';
+ }
+
+ //$d = '["hello world\\""]';
+ $d = '["\\\\\\"hello world,\\\\\\""]';
+ //$d = '["\\\\", "\\\\"]';
+ hex($d);
+ $test = new Services_JSON();
+ echo('<pre>');
+ print_r($d . "\n");
+ print_r($test->decode($d));
+ echo('</pre>');
+ */
+?> \ No newline at end of file
diff --git a/includes/js/dojox/grid/tests/support/movies.csv b/includes/js/dojox/grid/tests/support/movies.csv
new file mode 100644
index 0000000..baf71eb
--- /dev/null
+++ b/includes/js/dojox/grid/tests/support/movies.csv
@@ -0,0 +1,9 @@
+Title, Year, Producer
+City of God, 2002, Katia Lund
+Rain,, Christine Jeffs
+2001: A Space Odyssey, , Stanley Kubrick
+"This is a ""fake"" movie title", 1957, Sidney Lumet
+Alien, 1979 , Ridley Scott
+"The Sequel to ""Dances With Wolves.""", 1982, Ridley Scott
+"Caine Mutiny, The", 1954, "Dymtryk ""the King"", Edward"
+
diff --git a/includes/js/dojox/grid/tests/support/test_data.js b/includes/js/dojox/grid/tests/support/test_data.js
new file mode 100644
index 0000000..4707380
--- /dev/null
+++ b/includes/js/dojox/grid/tests/support/test_data.js
@@ -0,0 +1,30 @@
+// example sample data and code
+(function(){
+ // some sample data
+ // global var "data"
+ data = [
+ [ "normal", false, "new", 'But are not followed by two hexadecimal', 29.91, 10, false ],
+ [ "important", false, "new", 'Because a % sign always indicates', 9.33, -5, false ],
+ [ "important", false, "read", 'Signs can be selectively', 19.34, 0, true ],
+ [ "note", false, "read", 'However the reserved characters', 15.63, 0, true ],
+ [ "normal", false, "replied", 'It is therefore necessary', 24.22, 5.50, true ],
+ [ "important", false, "replied", 'To problems of corruption by', 9.12, -3, true ],
+ [ "note", false, "replied", 'Which would simply be awkward in', 12.15, -4, false ]
+ ];
+ var rows = 100;
+ for(var i=0, l=data.length; i<rows-l; i++){
+ data.push(data[i%l].slice(0));
+ }
+
+ // global var "model"
+ model = new dojox.grid.data.Table(null, data);
+
+ // simple display of row info; based on model observation
+ // global var "modelChange"
+ modelChange = function(){
+ var n = dojo.byId('rowCount');
+ if(n){
+ n.innerHTML = Number(model.getRowCount()) + ' row(s)';
+ }
+ }
+})();
diff --git a/includes/js/dojox/grid/tests/support/test_data_objects.js b/includes/js/dojox/grid/tests/support/test_data_objects.js
new file mode 100644
index 0000000..3d6e43a
--- /dev/null
+++ b/includes/js/dojox/grid/tests/support/test_data_objects.js
@@ -0,0 +1,31 @@
+// example sample data and code
+(function(){
+ // some sample data
+ // global var "data"
+ data = [
+ { col1: "normal", col2: false, col3: "new", col4: 'But are not followed by two hexadecimal', col5: 29.91, col6: 10, col7: false },
+ { col1: "important", col2: false, col3: "new", col4: 'Because a % sign always indicates', col5: 9.33, col6: -5, col7: false },
+ { col1: "important", col2: false, col3: "read", col4: 'Signs can be selectively', col5: 19.34, col6: 0, col7: true },
+ { col1: "note", col2: false, col3: "read", col4: 'However the reserved characters', col5: 15.63, col6: 0, col7: true },
+ { col1: "normal", col2: false, col3: "replied", col4: 'It is therefore necessary', col5: 24.22, col6: 5.50, col7: true },
+ { col1: "important", col2: false, col3: "replied", col4: 'To problems of corruption by', col5: 9.12, col6: -3, col7: true },
+ { col1: "note", col2: false, col3: "replied", col4: 'Which would simply be awkward in', col5: 12.15, col6: -4, col7: false }
+ ];
+ var rows = 100;
+ for(var i=0, l=data.length; i<rows-l; i++){
+ data.push(dojo.mixin({}, data[i%l]));
+ }
+
+ // global var "model"
+ model = new dojox.grid.data.Objects(null, [ { col1: "fake" } ]);
+ model2 = new dojox.grid.data.Objects(null, [ { col1: "fake" } ]);
+
+ // simple display of row info; based on model observation
+ // global var "modelChange"
+ modelChange = function(){
+ var n = dojo.byId('rowCount');
+ if(n){
+ n.innerHTML = Number(model.getRowCount()) + ' row(s)';
+ }
+ }
+})();
diff --git a/includes/js/dojox/grid/tests/support/testtbl.sql b/includes/js/dojox/grid/tests/support/testtbl.sql
new file mode 100644
index 0000000..ffe2af3
--- /dev/null
+++ b/includes/js/dojox/grid/tests/support/testtbl.sql
@@ -0,0 +1,944 @@
+/*
+MySQL Data Transfer
+Source Host: localhost
+Source Database: test
+Target Host: localhost
+Target Database: test
+Date: 12/14/2006 12:13:30 PM
+*/
+
+SET FOREIGN_KEY_CHECKS=0;
+-- ----------------------------
+-- Table structure for testtbl
+-- ----------------------------
+CREATE TABLE `testtbl` (
+ `Id` int(10) unsigned NOT NULL,
+ `Name` varchar(45) NOT NULL default '',
+ `Message` varchar(255) default NULL,
+ `Date` date default '2005-01-01',
+ PRIMARY KEY (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='InnoDB free: 4096 kB; InnoDB free: 4096 kB; InnoDB free: 409';
+
+-- ----------------------------
+-- Records
+-- ----------------------------
+INSERT INTO `testtbl` VALUES ('363', ' Lopez, Felipe', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('364', ' Lopez, Javy', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('365', ' Lopez, L', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('366', ' Lopez, Luis', ' 0.244', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('367', ' Lopez, Mendy', ' 0.241', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('368', ' Loretta, Mark', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('369', ' Lowell, Mike', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('370', ' Lugo, Julio', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('371', ' Lunar, Fernando', ' 0.246', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('372', ' Mabry, John', ' 0.208', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('373', ' Machado, Robert', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('374', ' Macias, Jose', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('375', ' Mackowiak, Rob', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('376', ' Magadan, Dave', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('377', ' Magee, Wendell', ' 0.213', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('378', ' Magruder, Chris', ' 0.172', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('379', ' Marrero, Eli', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('380', ' Martin, Al', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('381', ' Martinez, Dave', ' 0.287', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('382', ' Martinez, Edgar', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('383', ' Martinez, Felix', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('384', ' Martinez, Ramon', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('385', ' Martinez, Ramone', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('386', ' Martinez, Sandy', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('387', ' Martinez, Tino', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('388', ' Mateo, Henry', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('389', ' Mateo, Ruben', ' 0.248', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('390', ' Matheny, Mike', ' 0.218', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('391', ' Matos, Luis', ' 0.214', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('392', ' Mattess, Troy', ' 0.467', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('393', ' Matthews, Gary', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('394', ' Maurer, Dave', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('395', ' Maxwell, Jason', ' 0.191', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('396', ' Mayne, Brent', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('397', ' McCarty, David', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('398', ' McCracken, Quinton', ' 0.219', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('399', ' McDonald, Donzell', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('400', ' McDonald, John', ' 0.091', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('401', ' McDonald, Keith', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('402', ' McEwing, Joe', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('403', ' McGriff, Fred', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('404', ' McGuire, Ryan', ' 0.185', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('405', ' McGwire, Mark', ' 0.187', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('406', ' McLemore, Mark', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('407', ' McMillon, Billy', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('408', ' McRae, Scott', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('409', ' Meares, Pat', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('410', ' Melhuse, Adam', ' 0.183', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('411', ' Mendez, Donaldo', ' 0.153', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('412', ' Menechino, Frank', ' 0.242', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('413', ' Merced, Orlando', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('414', ' Merloni, Lou', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('415', ' Meyers, Chad', ' 0.118', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('416', ' Michaels, Jason', ' 0.167', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('417', ' Mientkiewicz, Doug', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('418', ' Millar, Kevin', ' 0.314', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('419', ' Miller, Corky', ' 0.184', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('420', ' Miller, Damian', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('421', ' Minor, Damion', ' 0.156', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('422', ' Minor, Ryan', ' 0.158', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('423', ' Mirabelli, Doug', ' 0.226', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('424', ' Moeller, Chad', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('425', ' Mohr, Dustan', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('426', ' Molina, Ben', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('427', ' Molina, Jose', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('428', ' Mondesi, Raul', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('429', ' Monroe, Craig', ' 0.212', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('430', ' Mora, Melvin', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('431', ' Mordecai, Mike', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('432', ' Morris, Warren', ' 0.204', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('433', ' Mottola, Chad', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('434', ' Mouton, James', ' 0.246', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('435', ' Mouton, Lyle', ' 0.059', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('436', ' Mueller, Bill', ' 0.295', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('437', ' Munson, Eric', ' 0.152', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('438', ' Murray, Calvin', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('439', ' Myers, Greg', ' 0.224', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('440', ' Nevin, Phil', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('441', ' Newhan, David', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('442', ' Nieves, Jose', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('443', ' Nixon, Trot', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('444', ' Norton, Greg', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('445', ' Nunez, Abraham', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('446', ' Ochoa, Alex', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('447', ' Offerman, Jose', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('448', ' Ojeda, Augie', ' 0.201', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('449', ' O\\\'Leary, Troy', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('450', ' Olerud, John', ' 0.302', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('451', ' Oliver, Joe', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('452', ' O\\\'Neill, Paul', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('453', ' Ordaz, Luis', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('454', ' Ordonez, Magglio', ' 0.305', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('455', ' Ordonez, Rey', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('456', ' Ortega, Bill', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('457', ' Ortiz, David', ' 0.234', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('458', ' Ortiz, Hector', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('459', ' Ortiz, Jose', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('460', ' Osik, Keith', ' 0.208', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('461', ' Overbay, Lyle', ' 0.5', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('462', ' Owens, Eric', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('463', ' Palmeiro, Orlando', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('464', ' Palmeiro, Rafael', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('465', ' Palmer, Dean', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('466', ' Paquette, Craig', ' 0.282', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('467', ' Patterson, Corey', ' 0.221', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('468', ' Patterson, Jarrod', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('469', ' Paul, Josh', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('470', ' Payton, Jay', ' 0.255', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('471', ' Pena, Angel', ' 0.204', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('472', ' Pena, Carlos', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('473', ' Pena, Elvis', ' 0.225', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('474', ' Perez, Eddie', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('475', ' Perez, Neifi', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('476', ' Perez, Robert', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('477', ' Perez, Santiago', ' 0.198', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('478', ' Perez, Thomas', ' 0.304', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('479', ' Perez, Timoniel', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('480', ' Perry, Herbert', ' 0.256', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('481', ' Peters, Chris', ' 0.091', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('482', ' Petrick, Ben', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('483', ' Phelps, Josh', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('484', ' Phillips, Jason', ' 0.143', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('485', ' Piatt, Adam', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('486', ' Piazza, Mike', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('487', ' Pickering, Calvin', ' 0.278', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('488', ' Pierre, Juan', ' 0.327', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('489', ' Pierzynski, A.J.', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('490', ' Podsednik, Scott', ' 0.167', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('491', ' Polanco, Placido', ' 0.307', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('492', ' Porter, Bo', ' 0.23', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('493', ' Posada, Jorge', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('494', ' Powell, Dante', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('495', ' Pratt, Todd', ' 0.185', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('496', ' Pride, Curtis', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('497', ' Prince, Tom', ' 0.219', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('498', ' Pujols, Albert', ' 0.329', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('499', ' Punto, Nick', ' 0.4', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('500', ' Quevado, Ruben', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('501', ' Quinn, Mark', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('502', ' Raines, Tim', ' 0.174', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('503', ' Raines, Tim', ' 0.303', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('504', ' Ramirez, Aramis', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('505', ' Ramirez, Julio', ' 0.081', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('506', ' Ramirez, Manny', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('507', ' Randa, Joe', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('508', ' Ransom, Cody', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('509', ' Reboulet, Jeff', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('510', ' Redman, Tim', ' 0.224', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('511', ' Redmond, Mike', ' 0.312', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('512', ' Reese, Pokey', ' 0.224', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('513', ' Relaford, Desi', ' 0.302', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('514', ' Renteria, Edgar', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('515', ' Richard, Chris', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('516', ' Riggs, Adam', ' 0.194', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('517', ' Rios, Armando', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('518', ' Ripken, Cal', ' 0.239', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('519', ' Rivas, Luis', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('520', ' Rivera, Juan', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('521', ' Rivera, Mike', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('522', ' Rivera, Ruben', ' 0.255', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('523', ' Roberts, Brian', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('524', ' Roberts, Dave', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('525', ' Robinson, Kerry', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('526', ' Rodriguez, Alex', ' 0.318', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('527', ' Rodriguez, Henry', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('528', ' Rodriguez, Ivan', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('529', ' Rolen, Scott', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('530', ' Rollins, Jimmy', ' 0.274', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('531', ' Rolls, Damian', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('532', ' Rowand, Aaron', ' 0.293', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('533', ' Ruffin, Johnny', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('534', ' Ryan, Rob', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('535', ' Sadler, Donnie', ' 0.162', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('536', ' Saenz, Olmedo', ' 0.22', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('537', ' Salmon, Tim', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('538', ' Sanchez, Alex', ' 0.206', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('539', ' Sanchez, Rey', ' 0.281', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('540', ' Sandberg, Jared', ' 0.206', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('541', ' Sanders, Anthony', ' 0.176', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('542', ' Sanders, Deion', ' 0.173', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('543', ' Sanders, Reggie', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('544', ' Santana, Pedro', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('545', ' Santangelo, F.P.', ' 0.197', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('546', ' Santiago, Benito', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('547', ' Santos, Angel', ' 0.125', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('548', ' Saturria, Luis', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('549', ' Schneider, Brian', ' 0.317', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('550', ' Schourek, Pete', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('551', ' Seabol, Scott', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('552', ' Sefcik, Kevin', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('553', ' Segui, David', ' 0.301', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('554', ' Seguignol, Fernando', ' 0.14', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('555', ' Selby, Bill', ' 0.228', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('556', ' Servais, Scott', ' 0.375', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('557', ' Sexson, Richie', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('558', ' Sheets, Andy', ' 0.196', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('559', ' Sheffield, Gary', ' 0.311', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('560', ' Sheldon, Scott', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('561', ' Shinjo, Tsuyoshi', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('562', ' Shumpert, Terry', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('563', ' Sierra, Ruben', ' 0.291', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('564', ' Simmons, Brian', ' 0.178', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('565', ' Simon, Randall', ' 0.305', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('566', ' Singleton, Chris', ' 0.298', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('567', ' Smith, Bobby', ' 0.105', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('568', ' Smith, Jason', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('569', ' Smith, Mark', ' 0.242', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('570', ' Snow, J.T.', ' 0.246', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('571', ' Sojo, Luis', ' 0.165', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('572', ' Soriano, Alfonso', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('573', ' Sosa, Juan', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('574', ' Sosa, Sammy', ' 0.328', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('575', ' Spencer, Shane', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('576', ' Spiers, Bill', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('577', ' Spiezio, Scott', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('578', ' Spivey, Junior', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('579', ' Sprague, Ed', ' 0.298', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('580', ' Stairs, Matt', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('581', ' Stevens, Lee', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('582', ' Stewart, Shannon', ' 0.316', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('583', ' Stinnett, Kelly', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('584', ' Stynes, Chris', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('585', ' Surhoff, B.J.', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('586', ' Sutton, Larry', ' 0.119', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('587', ' Suzuki, Ichiro', ' 0.35', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('588', ' Sweeney, Mark', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('589', ' Sweeney, Mike', ' 0.304', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('590', ' Tapani, Kevin', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('591', ' Tatis, Fernando', ' 0.255', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('592', ' Taubensee, Eddie', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('593', ' Taylor, Reggie', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('594', ' Tejada, Miguel', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('595', ' Thomas, Frank', ' 0.221', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('596', ' Thome, Jim', ' 0.291', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('597', ' Thompson, Ryan', ' 0.29', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('598', ' Toca, Jorge', ' 0.176', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('599', ' Torrealba, Steve', ' 0.5', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('600', ' Torrealba, Yorvit', ' 0.5', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('601', ' Tracy, Andy', ' 0.109', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('602', ' Trammell, Bubba', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('603', ' Truby, Chris', ' 0.206', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('604', ' Tucker, Michael', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('605', ' Tyner, Jason', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('606', ' Uribe, Juan', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('607', ' Valdez, Mario', ' 0.278', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('608', ' Valent, Eric', ' 0.098', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('609', ' Valentin, John', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('610', ' Valentin, Jose', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('611', ' VanderWal, John', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('612', ' Varitek, Jason', ' 0.293', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('613', ' Vaughn, Greg', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('614', ' Vazquez, Ramon', ' 0.229', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('615', ' Velandia, Jorge', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('616', ' Velarde, Randy', ' 0.278', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('617', ' Ventura, Robin', ' 0.237', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('618', ' Veras, Quilvio', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('619', ' Vidro, Jose', ' 0.319', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('620', ' Vina, Fernando', ' 0.303', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('621', ' Vizcaino, Jose', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('622', ' Vizquel, Omar', ' 0.255', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('623', ' Wakeland, Chris', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('624', ' Walbeck, Matt', ' 1', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('625', ' Walker, Larry', ' 0.35', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('626', ' Walker, Todd', ' 0.296', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('627', ' Ward, Daryle', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('628', ' Ward, Turner', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('629', ' Wehner, John', ' 0.196', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('630', ' Wells, Vernon', ' 0.313', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('631', ' White, Devon', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('632', ' White, Rondell', ' 0.307', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('633', ' Whiteside, Matt', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('634', ' Wilkerson, Brad', ' 0.205', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('635', ' Wilkins, Rick', ' 0.182', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('636', ' Williams, Bernie', ' 0.307', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('637', ' Williams, Gerald', ' 0.201', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('638', ' Williams, Matt', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('639', ' Wilson, Craig', ' 0.31', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('640', ' Wilson, Dan', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('641', ' Wilson, Enrique', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('642', ' Wilson, Jack', ' 0.223', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('643', ' Wilson, Preston', ' 0.274', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('644', ' Wilson, Tom', ' 0.19', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('645', ' Wilson, Vance', ' 0.298', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('646', ' Winn, Randy', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('647', ' Witt, Kevin', ' 0.185', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('648', ' Womack, Tony', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('649', ' Woodward, Chris', ' 0.19', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('650', ' Wooten, Shawn', ' 0.312', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('651', ' Young, Dmitri', ' 0.302', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('652', ' Young, Eric', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('653', ' Young, Kevin', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('654', ' Young, Mike', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('655', ' Zaun, Greg', ' 0.32', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('656', ' Zeile, Todd', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('657', ' Zuleta, Julio', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('658', ' Abernathy, Brent', ' 0.242', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('659', ' Abreu, Bob', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('660', ' Agbayani, Benny', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('661', ' Alcantara, Israel', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('662', ' Aldridge, Cory', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('663', ' Alfonzo, Edgardo', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('664', ' Alicea, Luis', ' 0.228', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('665', ' Allen, Chad', ' 0.1', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('666', ' Allen, Luke', ' 0.143', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('667', ' Alomar, Roberto', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('668', ' Alomar, Sandy', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('669', ' Alou, Moises', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('670', ' Alvarez, Tony', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('671', ' Amezaga, Alfredo', ' 0.538', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('672', ' Anderson, Brady', ' 0.163', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('673', ' Anderson, Garret', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('674', ' Anderson, Marlon', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('675', ' Andrews, Shane', ' 0.077', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('676', ' Arias, Alex', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('677', ' Aurilia, Rich', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('678', ' Ausmus, Brad', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('679', ' Aven, Bruce', ' 0.118', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('680', ' Baerga, Carlos', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('681', ' Bagwell, Jeff', ' 0.291', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('682', ' Bako, Paul', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('683', ' Banks, Brian', ' 0.321', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('684', ' Barajas, Rod', ' 0.234', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('685', ' Bard, Josh', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('686', ' Barker, Kevin', ' 0.158', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('687', ' Barrett, Michael', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('688', ' Batista, Tony', ' 0.244', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('689', ' Bautista, Danny', ' 0.325', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('690', ' Bell, David', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('691', ' Bell, Jay', ' 0.163', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('692', ' Belle, Albert', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('693', ' Bellhorn, Mark', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('694', ' Belliard, Ron', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('695', ' Bellinger, Clay', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('696', ' Beltran, Carlos', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('697', ' Beltre, Adrian', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('698', ' Benard, Marvin', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('699', ' Benjamin, Mike', ' 0.15', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('700', ' Bennett, Gary', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('701', ' Berg, David', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('702', ' Berger, Brandon', ' 0.201', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('703', ' Bergeron, Peter', ' 0.187', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('704', ' Berkman, Lance', ' 0.292', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('705', ' Berroa, Angel', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('706', ' Bigbie, Larry', ' 0.176', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('707', ' Biggio, Craig', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('708', ' Blake, Casey', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('709', ' Blalock, Hank', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('710', ' Blanco, Henry', ' 0.204', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('711', ' Bloomquist, Willie', ' 0.455', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('712', ' Blum, Geoff', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('713', ' Bocachica, Hiram', ' 0.22', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('714', ' Bonds, Barry', ' 0.37', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('715', ' Boone, Aaron', ' 0.241', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('716', ' Boone, Bret', ' 0.278', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('717', ' Borchard, Joe', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('718', ' Borders, Pat', ' 0.5', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('719', ' Bordick, Mike', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('720', ' Bradley, Milton', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('721', ' Bragg, Darren', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('722', ' Branyan, Russell', ' 0.228', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('723', ' Brito, Juan', ' 0.304', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('724', ' Broussard, Ben', ' 0.241', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('725', ' Brown, Adrian', ' 0.216', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('726', ' Brown, Dermal', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('727', ' Brown, Kevin', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('728', ' Brown, Roosevelt', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('729', ' Buchanan, Brian', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('730', ' Burks, Ellis', ' 0.301', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('731', ' Burnitz, Jeromy', ' 0.215', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('732', ' Burrell, Pat', ' 0.282', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('733', ' Burroughs, Sean', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('734', ' Bush, Homer', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('735', ' Butler, Brent', ' 0.259', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('736', ' Byrd, Marlon', ' 0.229', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('737', ' Byrnes, Eric', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('738', ' Cabrera, Jolbert', ' 0.143', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('739', ' Cabrera, Orlando', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('740', ' Cairo, Miguel', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('741', ' Cameron, Mike', ' 0.239', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('742', ' Canizaro, Jay', ' 0.214', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('743', ' Cardona, Javier', ' 0.103', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('744', ' Carroll, Jamey', ' 0.31', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('745', ' Caruso, Mike', ' 0.1', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('746', ' Casanova, Raul', ' 0.182', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('747', ' Casey, Sean', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('748', ' Cash, Kevin', ' 0.143', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('749', ' Castilla, Vinny', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('750', ' Castillo, Alberto', ' 0.135', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('751', ' Castillo, Luis', ' 0.305', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('752', ' Castro, Juan', ' 0.22', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('753', ' Castro, Ramon', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('754', ' Catalanotto, Frank', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('755', ' Cedeno, Roger', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('756', ' Cepicky, Matt', ' 0.216', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('757', ' Chavez, Endy', ' 0.296', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('758', ' Chavez, Eric', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('759', ' Chavez, Raul', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('760', ' Chen, Chin-Feng', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('761', ' Choi, Hee Seop', ' 0.18', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('762', ' Christensen, McKay', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('763', ' Christenson, Ryan', ' 0.155', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('764', ' Cintron, Alex', ' 0.213', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('765', ' Cirillo, Jeff', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('766', ' Clark, Brady', ' 0.192', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('767', ' Clark, Howie', ' 0.302', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('768', ' Clark, Tony', ' 0.207', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('769', ' Clayton, Royce', ' 0.251', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('770', ' Colangelo, Mike', ' 0.174', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('771', ' Colbrunn, Greg', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('772', ' Coleman, Michael', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('773', ' Collier, Lou', ' 0.091', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('774', ' Conine, Jeff', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('775', ' Conti, Jason', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('776', ' Coolbaugh, Mike', ' 0.083', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('777', ' Coomer, Ron', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('778', ' Cora, Alex', ' 0.291', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('779', ' Cordero, Wil', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('780', ' Cordova, Marty', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('781', ' Cota, Humberto', ' 0.294', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('782', ' Counsell, Craig', ' 0.282', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('783', ' Cox, Steve', ' 0.254', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('784', ' Crawford, Carl', ' 0.259', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('785', ' Crede, Joe', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('786', ' Crespo, Cesar', ' 0.172', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('787', ' Crisp, Covelli', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('788', ' Cruz, Deivi', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('789', ' Cruz, Ivan', ' 0.357', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('790', ' Cruz, Jacob', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('791', ' Cruz, Jose', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('792', ' Cuddyer, Michael', ' 0.259', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('793', ' Cust, Jack', ' 0.169', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('794', ' Damon, Johnny', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('795', ' Daubach, Brian', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('796', ' DaVanon, Jeff', ' 0.167', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('797', ' Davis, Ben', ' 0.259', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('798', ' Davis, J.J.', ' 0.1', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('799', ' Dawkins, Travis', ' 0.125', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('800', ' DeHaan, Kory', ' 0.091', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('801', ' Delgado, Carlos', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('802', ' Delgado, Wilson', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('803', ' Dellucci, David', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('804', ' DeRosa, Mark', ' 0.297', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('805', ' DeShields, Delino', ' 0.192', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('806', ' Diaz, Einar', ' 0.206', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('807', ' Diaz, Juan Carlos', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('808', ' DiFelice, Mike', ' 0.23', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('809', ' Donnels, Chris', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('810', ' Drew, J.D.', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('811', ' Dunn, Adam', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('812', ' Dunston, Shawon', ' 0.231', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('813', ' Dunwoody, Todd', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('814', ' Durazo, Erubiel', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('815', ' Durham, Ray', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('816', ' Dye, Jermaine', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('817', ' Easley, Damion', ' 0.224', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('818', ' Echevarria, Angel', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('819', ' Eckstein, David', ' 0.293', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('820', ' Edmonds, Jim', ' 0.311', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('821', ' Ellis, Mark', ' 0.272', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('822', ' Encarnacion, Juan', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('823', ' Encarnacion, Mario', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('824', ' Ensberg, Morgan', ' 0.242', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('825', ' Erstad, Darin', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('826', ' Escalona, Felix', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('827', ' Escobar, Alex', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('828', ' Estalella, Bobby', ' 0.205', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('829', ' Estrada, Johnny', ' 0.118', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('830', ' Everett, Adam', ' 0.193', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('831', ' Everett, Carl', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('832', ' Fabregas, Jorge', ' 0.181', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('833', ' Fasano, Sal', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('834', ' Febles, Carlos', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('835', ' Feliz, Pedro', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('836', ' Fick, Robert', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('837', ' Figgins, Chone', ' 0.167', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('838', ' Finley, Steve', ' 0.287', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('839', ' Flaherty, John', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('840', ' Fletcher, Darrin', ' 0.22', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('841', ' Flores, Jose', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('842', ' Floyd, Cliff', ' 0.288', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('843', ' Fordyce, Brook', ' 0.231', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('844', ' Fox, Andy', ' 0.251', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('845', ' Franco, Julio', ' 0.284', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('846', ' Franco, Matt', ' 0.317', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('847', ' Fryman, Travis', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('848', ' Fullmer, Brad', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('849', ' Furcal, Rafael', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('850', ' Galarraga, Andres', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('851', ' Gant, Ron', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('852', ' Garcia, Jesse', ' 0.197', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('853', ' Garcia, Karim', ' 0.297', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('854', ' Garcia, Luis', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('855', ' Garciaparra, Nomar', ' 0.31', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('856', ' German, Esteban', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('857', ' Giambi, Jason', ' 0.314', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('858', ' Giambi, Jeremy', ' 0.259', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('859', ' Gibbons, Jay', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('860', ' Gil, Benji', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('861', ' Gil, Geronimo', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('862', ' Giles, Brian', ' 0.298', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('863', ' Giles, Marcus', ' 0.23', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('864', ' Ginter, Keith', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('865', ' Gipson, Charles', ' 0.236', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('866', ' Girardi, Joe', ' 0.226', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('867', ' Glanville, Doug', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('868', ' Glaus, Troy', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('869', ' Gload, Ross', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('870', ' Gomez, Alexis', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('871', ' Gomez, Chris', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('872', ' Gonzalez, Alex', ' 0.225', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('873', ' Gonzalez, Alex', ' 0.248', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('874', ' Gonzalez, Juan', ' 0.282', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('875', ' Gonzalez, Luis', ' 0.288', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('876', ' Gonzalez, Raul', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('877', ' Gonzalez, Wiki', ' 0.22', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('878', ' Goodwin, Tom', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('879', ' Grabowski, Jason', ' 0.375', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('880', ' Grace, Mark', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('881', ' Graffanino, Tony', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('882', ' Green, Nick', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('883', ' Green, Shawn', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('884', ' Greene, Todd', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('885', ' Greer, Rusty', ' 0.296', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('886', ' Grieve, Ben', ' 0.251', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('887', ' Griffey, Ken', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('888', ' Grissom, Marquis', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('889', ' Grudzielanek, Mark', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('890', ' Guerrero, Vladimir', ' 0.336', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('891', ' Guerrero, Wilton', ' 0.221', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('892', ' Guiel, Aaron', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('893', ' Guillen, Carlos', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('894', ' Guillen, Jose', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('895', ' Gutierrez, Ricky', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('896', ' Guzman, Christian', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('897', ' Hafner, Travis', ' 0.242', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('898', ' Hairston, Jerry', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('899', ' Hall, Bill', ' 0.194', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('900', ' Hall, Toby', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('901', ' Halter, Shane', ' 0.239', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('902', ' Hammonds, Jeffrey', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('903', ' Hansen, Dave', ' 0.292', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('904', ' Harris, Lenny', ' 0.305', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('905', ' Harris, Willie', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('906', ' Hart, Jason', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('907', ' Haselman, Bill', ' 0.246', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('908', ' Hatteberg, Scott', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('909', ' Helms, Wes', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('910', ' Helton, Todd', ' 0.329', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('911', ' Henderson, Rickey', ' 0.223', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('912', ' Henson, Drew', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('913', ' Hermansen, Chad', ' 0.207', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('914', ' Hernandez, Jose', ' 0.288', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('915', ' Hernandez, Ramon', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('916', ' Hidalgo, Richard', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('917', ' Higginson, Bobby', ' 0.282', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('918', ' Hill, Bobby', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('919', ' Hillenbrand, Shea', ' 0.293', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('920', ' Hinch, A.J.', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('921', ' Hinske, Eric', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('922', ' Hocking, Denny', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('923', ' Hollandsworth, Todd', ' 0.284', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('924', ' Hollins, Dave', ' 0.118', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('925', ' Hoover, Paul', ' 0.176', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('926', ' Houston, Tyler', ' 0.281', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('927', ' Hubbard, Trenidad', ' 0.209', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('928', ' Huckaby, Ken', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('929', ' Hudson, Orlando', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('930', ' Huff, Aubrey', ' 0.313', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('931', ' Hundley, Todd', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('932', ' Hunter, Brian L.', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('933', ' Hunter, Torii', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('934', ' Hyzdu, Adam', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('935', ' Ibanez, Raul', ' 0.294', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('936', ' Infante, Omar', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('937', ' Inge, Brandon', ' 0.202', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('938', ' Izturis, Cesar', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('939', ' Jackson, Damian', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('940', ' Jackson, Ryan', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('941', ' Jenkins, Geoff', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('942', ' Jensen, Marcus', ' 0.114', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('943', ' Jeter, Derek', ' 0.297', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('944', ' Jimenez, D\\\'Angelo', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('945', ' Johnson, Charles', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('946', ' Johnson, Mark', ' 0.209', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('947', ' Johnson, Mark P.', ' 0.137', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('948', ' Johnson, Nick', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('949', ' Johnson, Russ', ' 0.216', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('950', ' Jones, Andruw', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('951', ' Jones, Chipper', ' 0.327', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('952', ' Jones, Jacque', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('953', ' Jordan, Brian', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('954', ' Jose, Felix', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('955', ' Justice, David', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('956', ' Kapler, Gabe', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('957', ' Karros, Eric', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('958', ' Kearns, Austin', ' 0.315', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('959', ' Kelly, Kenny', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('960', ' Kendall, Jason', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('961', ' Kennedy, Adam', ' 0.312', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('962', ' Kent, Jeff', ' 0.313', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('963', ' Kielty, Bobby', ' 0.291', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('964', ' Kingsale, Eugene', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('965', ' Kinkade, Mike', ' 0.38', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('966', ' Klassen, Danny', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('967', ' Klesko, Ryan', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('968', ' Knoblauch, Chuck', ' 0.21', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('969', ' Konerko, Paul', ' 0.304', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('970', ' Koskie, Corey', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('971', ' Kotsay, Mark', ' 0.292', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('972', ' Kreuter, Chad', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('973', ' Lamb, David', ' 0.1', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('974', ' Lamb, Mike', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('975', ' Lampkin, Tom', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('976', ' Lane, Jason', ' 0.29', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('977', ' Langerhans, Ryan', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('978', ' Lankford, Ray', ' 0.224', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('979', ' Larkin, Barry', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('980', ' LaRocca, Greg', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('981', ' Larson, Brandon', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('982', ' LaRue, Jason', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('983', ' Lawrence, Joe', ' 0.18', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('984', ' Lawton, Matt', ' 0.236', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('985', ' LeCroy, Matt', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('986', ' Ledee, Ricky', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('987', ' Lee, Carlos', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('988', ' Lee, Derrek', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('989', ' Lee, Travis', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('990', ' Leon, Jose', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('991', ' Lesher, Brian', ' 0.132', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('992', ' Lewis, Darren', ' 0.241', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('993', ' Lieberthal, Mike', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('994', ' Liefer, Jeff', ' 0.23', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('995', ' Little, Mark', ' 0.208', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('996', ' Lo Duca, Paul', ' 0.281', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('997', ' Lockhart, Keith', ' 0.216', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('998', ' Lofton, Kenny', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('999', ' Lombard, George', ' 0.241', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1000', ' Long, Terrence', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1001', ' Lopez, Felipe', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1002', ' Lopez, Javy', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1003', ' Lopez, Luis', ' 0.197', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1004', ' Lopez, Mendy', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1005', ' Loretta, Mark', ' 0.304', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1006', ' Lowell, Mike', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1007', ' Ludwick, Ryan', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1008', ' Lugo, Julio', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1009', ' Lunar, Fernando', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1010', ' Lunsford, Trey', ' 0.667', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1011', ' Mabry, John', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1012', ' Machado, Robert', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1013', ' Macias, Jose', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1014', ' Mackowiak, Rob', ' 0.244', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1015', ' Magee, Wendell', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1016', ' Magruder, Chris', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1017', ' Mahoney, Mike', ' 0.207', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1018', ' Malloy, Marty', ' 0.12', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1019', ' Marrero, Eli', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1020', ' Martinez, Dave', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1021', ' Martinez, Edgar', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1022', ' Martinez, Ramon', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1023', ' Martinez, Tino', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1024', ' Martinez, Victor', ' 0.281', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1025', ' Mateo, Henry', ' 0.174', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1026', ' Mateo, Ruben', ' 0.256', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1027', ' Matheny, Mike', ' 0.244', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1028', ' Matos, Julios', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1029', ' Matos, Luis', ' 0.129', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1030', ' Matthews, Gary', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1031', ' Mayne, Brent', ' 0.236', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1032', ' McCarty, David', ' 0.136', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1033', ' McCracken, Quinton', ' 0.309', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1034', ' McDonald, Donzell', ' 0.182', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1035', ' McDonald, John', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1036', ' McEwing, Joe', ' 0.199', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1037', ' McGriff, Fred', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1038', ' McGuire, Ryan', ' 0.077', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1039', ' McKay, Cody', ' 0.667', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1040', ' McKeel, Walt', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1041', ' McLemore, Mark', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1042', ' Meares, Pat', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1043', ' Meluskey, Mitch', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1044', ' Mench, Kevin', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1045', ' Menechino, Frank', ' 0.205', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1046', ' Merced, Orlando', ' 0.287', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1047', ' Merloni, Lou', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1048', ' Michaels, Jason', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1049', ' Mientkiewicz, Doug', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1050', ' Millar, Kevin', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1051', ' Miller, Corky', ' 0.254', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1052', ' Miller, Damian', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1053', ' Minor, Damon', ' 0.237', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1054', ' Mirabelli, Doug', ' 0.225', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1055', ' Moeller, Chad', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1056', ' Mohr, Dustan', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1057', ' Molina, Ben', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1058', ' Molina, Izzy', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1059', ' Molina, Jose', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1060', ' Mondesi, Raul', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1061', ' Monroe, Craig', ' 0.12', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1062', ' Mora, Melvin', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1063', ' Mordecai, Mike', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1064', ' Moriarty, Mike', ' 0.188', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1065', ' Morris, Warren', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1066', ' Mueller, Bill', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1067', ' Munson, Eric', ' 0.186', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1068', ' Murray, Calvin', ' 0.146', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1069', ' Myers, Greg', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1070', ' Nelson, Bryant', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1071', ' Nevin, Phil', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1072', ' Nieves, Jose', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1073', ' Nieves, Wil', ' 0.181', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1074', ' Nixon, Trot', ' 0.256', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1075', ' Norton, Greg', ' 0.22', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1076', ' Nunez, Abraham', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1077', ' Nunez, Abraham', ' 0.118', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1078', ' O\\\'Leary, Troy', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1079', ' Ochoa, Alex', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1080', ' Offerman, Jose', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1081', ' Ojeda, Augie', ' 0.186', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1082', ' Olerud, John', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1083', ' Olivo, Miguel', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1084', ' Ordaz, Luis', ' 0.223', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1085', ' Ordonez, Magglio', ' 0.32', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1086', ' Ordonez, Rey', ' 0.254', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1087', ' Orie, Kevin', ' 0.281', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1088', ' Ortiz, David', ' 0.272', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1089', ' Ortiz, Hector', ' 0.214', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1090', ' Ortiz, Jose', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1091', ' Osik, Keith', ' 0.16', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1092', ' Overbay, Lyle', ' 0.1', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1093', ' Owens, Eric', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1094', ' Ozuna, Pablo', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1095', ' Palmeiro, Orlando', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1096', ' Palmeiro, Rafael', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1097', ' Palmer, Dean', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1098', ' Paquette, Craig', ' 0.194', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1099', ' Patterson, Corey', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1100', ' Paul, Josh', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1101', ' Payton, Jay', ' 0.303', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1102', ' Pelaez, Alex', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1103', ' Pellow, Kip', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1104', ' Pena, Carlos', ' 0.242', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1105', ' Pena, Wily Mo', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1106', ' Perez, Eddie', ' 0.214', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1107', ' Perez, Eduardo', ' 0.201', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1108', ' Perez, Neifi', ' 0.236', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1109', ' Perez, Timoniel', ' 0.295', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1110', ' Perez, Tomas', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1111', ' Perry, Chan', ' 0.091', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1112', ' Perry, Herbert', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1113', ' Petrick, Ben', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1114', ' Phelps, Josh', ' 0.309', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1115', ' Phillips, Brandon', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1116', ' Phillips, Jason', ' 0.368', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1117', ' Piatt, Adam', ' 0.234', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1118', ' Piazza, Mike', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1119', ' Pickering, Calvin', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1120', ' Pierre, Juan', ' 0.287', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1121', ' Pierzynski, A.J.', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1122', ' Podsednik, Scott', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1123', ' Polanco, Placido', ' 0.288', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1124', ' Posada, Jorge', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1125', ' Pratt, Todd', ' 0.311', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1126', ' Prince, Tom', ' 0.224', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1127', ' Pujols, Albert', ' 0.314', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1128', ' Punto, Nick', ' 0.167', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1129', ' Quinn, Mark', ' 0.237', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1130', ' Raines, Tim', ' 0.191', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1131', ' Ramirez, Aramis', ' 0.234', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1132', ' Ramirez, Julio', ' 0.281', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1133', ' Ramirez, Manny', ' 0.349', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1134', ' Randa, Joe', ' 0.282', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1135', ' Ransom, Cody', ' 0.667', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1136', ' Reboulet, Jeff', ' 0.208', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1137', ' Redmond, Mike', ' 0.305', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1138', ' Reese, Pokey', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1139', ' Relaford, Desi', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1140', ' Renteria, Edgar', ' 0.305', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1141', ' Restovich, Mike', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1142', ' Richard, Chris', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1143', ' Rios, Armando', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1144', ' Rivas, Luis', ' 0.256', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1145', ' Rivera, Juan', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1146', ' Rivera, Mike', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1147', ' Rivera, Ruben', ' 0.209', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1148', ' Roberts, Brian', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1149', ' Roberts, Dave', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1150', ' Robinson, Kerry', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1151', ' Rodriguez, Alex', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1152', ' Rodriguez, Henry', ' 0.05', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1153', ' Rodriguez, Ivan', ' 0.314', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1154', ' Rogers, Ed', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1155', ' Rolen, Scott', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1156', ' Rollins, Jimmy', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1157', ' Rolls, Damian', ' 0.292', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1158', ' Romano, Jason', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1159', ' Ross, David', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1160', ' Rowand, Aaron', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1161', ' Ruan, Wilken', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1162', ' Rushford, Jim', ' 0.143', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1163', ' Ryan, Mike', ' 0.091', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1164', ' Sadler, Donnie', ' 0.163', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1165', ' Saenz, Olmedo', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1166', ' Salazar, Oscar', ' 0.19', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1167', ' Salmon, Tim', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1168', ' Sanchez, Alex', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1169', ' Sanchez, Freddy', ' 0.188', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1170', ' Sanchez, Rey', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1171', ' Sandberg, Jared', ' 0.229', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1172', ' Sanders, Reggie', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1173', ' Santiago, Benito', ' 0.278', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1174', ' Santiago, Ramon', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1175', ' Schneider, Brian', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1176', ' Scutaro, Marcos', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1177', ' Sears, Todd', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1178', ' Segui, David', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1179', ' Selby, Bill', ' 0.214', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1180', ' Sexson, Richie', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1181', ' Sheets, Andy', ' 0.248', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1182', ' Sheffield, Gary', ' 0.307', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1183', ' Shinjo, Tsuyoshi', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1184', ' Shumpert, Terry', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1185', ' Sierra, Ruben', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1186', ' Simon, Randall', ' 0.301', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1187', ' Singleton, Chris', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1188', ' Smith, Bobby', ' 0.175', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1189', ' Smith, Jason', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1190', ' Snead, Esix', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1191', ' Snelling, Chris', ' 0.148', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1192', ' Snow, J.T.', ' 0.246', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1193', ' Snyder, Earl', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1194', ' Soriano, Alfonso', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1195', ' Sosa, Sammy', ' 0.288', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1196', ' Spencer, Shane', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1197', ' Spiezio, Scott', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1198', ' Spivey, Junior', ' 0.301', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1199', ' Stairs, Matt', ' 0.244', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1200', ' Stevens, Lee', ' 0.204', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1201', ' Stewart, Shannon', ' 0.303', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1202', ' Stinnett, Kelly', ' 0.226', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1203', ' Stynes, Chris', ' 0.241', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1204', ' Surhoff, B.J.', ' 0.293', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1205', ' Sutton, Larry', ' 0.105', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1206', ' Suzuki, Ichiro', ' 0.321', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1207', ' Swann, Pedro', ' 0.083', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1208', ' Sweeney, Mark', ' 0.169', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1209', ' Sweeney, Mike', ' 0.34', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1210', ' Taguchi, So', ' 0.4', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1211', ' Tarasco, Tony', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1212', ' Tatis, Fernando', ' 0.228', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1213', ' Taubensee, Eddie', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1214', ' Taylor, Reggie', ' 0.254', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1215', ' Tejada, Miguel', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1216', ' Thames, Marcus', ' 0.231', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1217', ' Thomas, Frank', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1218', ' Thome, Jim', ' 0.304', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1219', ' Thompson, Ryan', ' 0.248', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1220', ' Thurston, Joe', ' 0.462', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1221', ' Toca, Jorge', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1222', ' Torcato, Tony', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1223', ' Torrealba, Steve', ' 0.059', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1224', ' Torrealba, Yorvit', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1225', ' Torres, Andres', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1226', ' Trammell, Bubba', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1227', ' Truby, Chris', ' 0.215', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1228', ' Tucker, Michael', ' 0.248', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1229', ' Tyner, Jason', ' 0.214', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1230', ' Ugueto, Luis', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1231', ' Uribe, Juan', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1232', ' Valdez, Mario', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1233', ' Valent, Eric', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1234', ' Valentin, Javier', ' 0.5', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1235', ' Valentin, John', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1236', ' Valentin, Jose', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1237', ' Vander Wal, John', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1238', ' Varitek, Jason', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1239', ' Vaughn, Greg', ' 0.163', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1240', ' Vaughn, Mo', ' 0.259', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1241', ' Vazquez, Ramon', ' 0.274', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1242', ' Velarde, Randy', ' 0.226', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1243', ' Ventura, Robin', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1244', ' Vidro, Jose', ' 0.315', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1245', ' Vina, Fernando', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1246', ' Vizcaino, Jose', ' 0.303', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1247', ' Vizquel, Omar', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1248', ' Walbeck, Matt', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1249', ' Walker, Larry', ' 0.338', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1250', ' Walker, Todd', ' 0.299', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1251', ' Ward, Daryle', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1252', ' Wathan, Dusty', ' 0.6', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1253', ' Wells, Vernon', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1254', ' Werth, Jayson', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1255', ' Wesson, Barry', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1256', ' White, Rondell', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1257', ' Widger, Chris', ' 0.297', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1258', ' Wigginton, Ty', ' 0.302', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1259', ' Wilkerson, Brad', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1260', ' Williams, Bernie', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1261', ' Williams, Gerald', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1262', ' Williams, Matt', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1263', ' Wilson, Craig', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1264', ' Wilson, Dan', ' 0.295', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1265', ' Wilson, Enrique', ' 0.181', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1266', ' Wilson, Jack', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1267', ' Wilson, Preston', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1268', ' Wilson, Tom', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1269', ' Wilson, Vance', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1270', ' Winn, Randy', ' 0.298', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1271', ' Wise, DeWayne', ' 0.179', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1272', ' Womack, Tony', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1273', ' Woodward, Chris', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1274', ' Wooten, Shawn', ' 0.292', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1275', ' Wright, Ron', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1276', ' Young, Dmitri', ' 0.284', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1277', ' Young, Eric', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1278', ' Young, Kevin', ' 0.246', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1279', ' Young, Michael', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1280', ' Zaun, Greg', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1281', ' Zeile, Todd', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1282', ' Zinter, Alan', ' 0.136', '2005-01-01');
diff --git a/includes/js/dojox/grid/tests/support/yahoo_search.js b/includes/js/dojox/grid/tests/support/yahoo_search.js
new file mode 100644
index 0000000..a013b5d
--- /dev/null
+++ b/includes/js/dojox/grid/tests/support/yahoo_search.js
@@ -0,0 +1,131 @@
+// model that works with Yahoo Search API
+dojo.declare("dojox.grid.data.yahooSearch", dojox.grid.data.dynamic,
+ function(inFields, inData) {
+ this.rowsPerPage = 20;
+ this.fieldNames = [];
+ for (var i=0, f; (f=inFields[i]); i++)
+ this.fieldNames.push(f.name);
+ }, {
+ clearData: function() {
+ turbo.widgets.TurboGrid.data.dynamic.prototype.clearData.apply(this, arguments);
+ },
+ // server send / receive
+ encodeParam: function(inName, inValue) {
+ return turbo.printf('&%s=%s', inName, inValue);
+ },
+ getParams: function(inParams) {
+ var url = this.url;
+ url += '?appid=turboajax';
+ inParams = inParams || {};
+ inParams.output = 'json';
+ inParams.results = this.rowsPerPage;
+ inParams.query = turbo.$('searchInput').value.replace(/ /g, '+');
+ for (var i in inParams)
+ if (inParams[i] != undefined)
+ url += this.encodeParam(i, inParams[i]);
+ return url;
+ },
+ send: function(inAsync, inParams, inOnReceive, inOnError) {
+ var p = this.getParams(inParams);
+ dojo.io.bind({
+ url: "support/proxy.php",
+ method: "post",
+ content: {url: p },
+ contentType: "application/x-www-form-urlencoded; charset=utf-8",
+ mimetype: 'text/json',
+ sync: !inAsync,
+ load: turbo.bindArgs(this, "receive", inOnReceive, inOnError),
+ error: turbo.bindArgs(this, "error", inOnError)
+ });
+ this.onSend(inParams);
+ },
+ receive: function(inOnReceive, inOnError, inEvt, inData) {
+ try {
+ inData = inData.ResultSet;
+ inOnReceive(inData);
+ this.onReceive(inData);
+ } catch(e) {
+ if (inOnError)
+ inOnError(inData);
+ }
+ },
+ error: function(inOnError, inTyp, inErr) {
+ var m = 'io error: ' + inErr.message;
+ alert(m);
+ if (inOnError)
+ inOnError(m);
+ },
+ fetchRowCount: function(inCallback) {
+ this.send(true, inCallback );
+ },
+ // request data
+ requestRows: function(inRowIndex, inCount) {
+ inRowIndex = (inRowIndex == undefined ? 0 : inRowIndex);
+ var params = {
+ start: inRowIndex + 1
+ }
+ this.send(true, params, turbo.bindArgs(this, this.processRows));
+ },
+ // server callbacks
+ processRows: function(inData) {
+ for (var i=0, l=inData.totalResultsReturned, s=inData.firstResultPosition; i<l; i++) {
+ this.setRow(inData.Result[i], s - 1 + i);
+ }
+ // yahoo says 1000 is max results to return
+ var c = Math.min(1000, inData.totalResultsAvailable);
+ if (this.count != c) {
+ this.setRowCount(c);
+ this.allChange();
+ this.onInitializeData(inData);
+ }
+ },
+ getDatum: function(inRowIndex, inColIndex) {
+ var row = this.getRow(inRowIndex);
+ var field = this.fields.get(inColIndex);
+ return (inColIndex == undefined ? row : (row ? row[field.name] : field.na));
+ },
+ // events
+ onInitializeData: turbo.nop,
+ onSend: turbo.nop,
+ onReceive: turbo.nop
+});
+
+// report
+modelChange = function() {
+ var n = turbo.$('rowCount');
+ if (n)
+ n.innerHTML = turbo.printf('about %s row(s)', model.count);
+}
+
+
+// some data formatters
+formatLink = function(inData, inRowIndex) {
+ if (!inData[0] || !inData[1])
+ return '&nbsp;';
+ return turbo.supplant('<a target="_blank" href="{href}">{text}</a>', {href: inData[0], text: inData[1] });
+};
+
+formatImage = function(inData, inRowIndex) {
+ if (!inData[0] || !inData[1])
+ return '&nbsp;';
+ var o = {
+ href: inData[0],
+ src: inData[1].Url,
+ width: inData[1].Width,
+ height: inData[1].Height
+ }
+ return turbo.supplant('<a href="{href}" target="_blank"><img border=0 src="{src}" width="{width}" height="{height}"></a>', o);
+};
+
+formatDate = function(inDatum, inRowIndex) {
+ if (inDatum == '')
+ return '&nbsp;';
+ var d = new Date(inDatum * 1000);
+ return turbo.printf('%s/%s/%s', d.getMonth(), d.getDate(), d.getFullYear());
+};
+
+formatDimensions = function(inData, inRowIndex) {
+ if (!inData[0] || !inData[1])
+ return '&nbsp;';
+ return inData[0] + ' x ' + inData[1];
+}
diff --git a/includes/js/dojox/grid/tests/test_change_structure.html b/includes/js/dojox/grid/tests/test_change_structure.html
new file mode 100644
index 0000000..4ecfa71
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_change_structure.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid Change Structure Example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ width: 48em;
+ height: 30em;
+ }
+
+ #grid .dojoxGrid-cell {
+ text-align: center;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript">
+
+ // get can return data for a cell of the grid
+ function get(inRowIndex) {
+ return [this.index, inRowIndex].join(', ');
+ }
+
+ // grid structure
+ // a grid view is a group of columns
+
+ // a special view providing selection feedback
+ var rowBar = {type: 'dojox.GridRowView', width: '20px' };
+
+ // a view without scrollbars
+ var view0 = {
+ noscroll: true,
+ cells: [[
+ {name: 'Alpha', value: '<input name="" type="checkbox" value="0">'},
+ {name: 'Beta', get: get, width: 4.5}
+ ]]};
+
+ var view1 = {
+ cells: [[
+ {name: 'Apple', value: '<button>Apple</button>'},
+ {name: 'Banana', get: get},
+ {name: 'Beans', value: 'Happy to be grid!'},
+ {name: 'Kiwi', get: get},
+ {name: 'Orange', value: '<img src="images/flatScreen.gif" height="48" width="48">'},
+ {name: 'Pear', get: get},
+ {name: 'Tomato', width: 20, value: '<input name="" type="file">'},
+ ]]};
+
+ var view2 = {
+ noscroll: true,
+ cells: [
+ [
+ {name: 'Alpha', value: '<input name="" type="checkbox" value="0">', rowSpan: 2},
+ {name: 'Beta', get: get, width: 4.5}
+ ], [
+ {name: 'Gamma', get: get}
+ ],
+ [
+ {name: 'Epsilon', value: '<button>Epsilon</button>', colSpan: 2}
+ ]
+ ]
+ }
+
+ var view3 = {
+ cells: [
+ [
+ {name: 'Apple', value: '<button>Apple</button>', rowSpan: 3},
+ {name: 'Banana', get: get, width: 20},
+ {name: 'Kiwi', get: get, width: 20},
+ {name: 'Pear', get: get, width: 20},
+ ],
+ [
+ {name: 'Beans', value: 'Happy to be grid!'},
+ {name: 'Orange', value: '<img src="images/flatScreen.gif" height="48" width="48">'},
+ {name: 'Tomato', value: '<input name="" type="file">'}
+ ], [
+ {name: 'Zuchini', value: '<span style="letter-spacing: 10em;">wide</span>', colSpan: 3}
+ ]
+ ]};
+
+
+ // a grid structure is an array of views.
+ // By default the middle view will be 'elastic', sized to fit the remaining space left by other views
+ // grid.elasticView can also be manually set
+ var structure = [ rowBar, view0, view1 ];
+ var structure2 = [ rowBar, view2, view3 ];
+
+
+ var l2 = false;
+ toggleStructure = function() {
+ l2 = !l2;
+ grid.scrollToRow(0);
+ grid.setStructure(l2 ? structure2 : structure);
+ }
+
+ dojo.addOnLoad(function() {
+ window["grid"] = dijit.byId("grid");
+ });
+</script>
+</head>
+<body>
+<div class="heading">dojox.VirtualGrid Change Structure Example</div>
+<p>
+ <button onclick="toggleStructure()">Change Structure</button>
+</p>
+<div id="grid" dojoType="dojox.VirtualGrid" structure="structure" rowCount="100000" elasticView="2"></div>
+
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_custom_sort.html b/includes/js/dojox/grid/tests/test_custom_sort.html
new file mode 100644
index 0000000..51b0cf3
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_custom_sort.html
@@ -0,0 +1,86 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>Custom Sort Test - dojox.Grid</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ width: 35em;
+ height: 30em;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+ <!--<script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>-->
+ <!-- Debugging -->
+ <script type="text/javascript" src="../_grid/lib.js"></script>
+ <script type="text/javascript" src="../_grid/drag.js"></script>
+ <script type="text/javascript" src="../_grid/scroller.js"></script>
+ <script type="text/javascript" src="../_grid/builder.js"></script>
+ <script type="text/javascript" src="../_grid/cell.js"></script>
+ <script type="text/javascript" src="../_grid/layout.js"></script>
+ <script type="text/javascript" src="../_grid/rows.js"></script>
+ <script type="text/javascript" src="../_grid/focus.js"></script>
+ <script type="text/javascript" src="../_grid/selection.js"></script>
+ <script type="text/javascript" src="../_grid/edit.js"></script>
+ <script type="text/javascript" src="../_grid/view.js"></script>
+ <script type="text/javascript" src="../_grid/views.js"></script>
+ <script type="text/javascript" src="../_grid/rowbar.js"></script>
+ <script type="text/javascript" src="../_grid/publicEvents.js"></script>
+ <script type="text/javascript" src="../VirtualGrid.js"></script>
+ <script type="text/javascript" src="../_data/fields.js"></script>
+ <script type="text/javascript" src="../_data/model.js"></script>
+ <script type="text/javascript" src="../_data/editors.js"></script>
+ <script type="text/javascript" src="../Grid.js"></script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ // here is a custom compare function that can drive the sorting engine
+ // of course, this is only valid for client-side data sets
+ compare2ndLetter = function(inA, inB) {
+ // sort on the second letter
+ // return <0, 0, >0
+ return inA.charCodeAt(1) - inB.charCodeAt(1);
+ }
+
+ // custom compare functions for sorting belong to the data model
+ // data model keeps this kind of metadata in a object called 'fields'
+
+ // you can install the custom compare function directly into fields
+ // model.fields.get(3).compare = compare2ndLetter;
+
+ // or you could setup fields when instantiating the model
+ model = new dojox.grid.data.Table([{}, {}, {}, {compare: compare2ndLetter}], data);
+
+ // a grid view is a group of columns
+ var view1 = {
+ cells: [[
+ {name: 'Column 0'}, {name: 'Column 1'}, {name: 'Column 2'}, {name: 'Column 3', width: "auto"}, {name: 'Column 4'}
+ ],[
+ {name: 'Column 5'}, {name: 'Column 6'}, {name: 'Column 7'}, {name: 'Column 8', field: 3, colSpan: 2}
+ ]]
+ };
+ // a grid layout is an array of views.
+ var layout = [ view1 ];
+</script>
+</head>
+<body>
+<div class="heading">dojox.Grid Custom Sort Test</div>
+<br />
+<b>Column 3</b>'s data field has a custom sorter that sorts by the 2nd letter in the string.
+<br /><br />
+<div id="grid" dojoType="dojox.Grid" model="model" structure="layout"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_dojo_data_edit.html b/includes/js/dojox/grid/tests/test_dojo_data_edit.html
new file mode 100644
index 0000000..7c9bc5c
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_dojo_data_edit.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>Test dojox.Grid Editing with DojoData model</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+<style>
+ @import "../_grid/Grid.css";
+ body {
+ font-family: Tahoma, Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ }
+ .dojoxGrid-row-editing td {
+ background-color: #F4FFF4;
+ }
+ .dojoxGrid input, .dojoxGrid select, .dojoxGrid textarea {
+ margin: 0;
+ padding: 0;
+ border-style: none;
+ width: 100%;
+ font-size: 100%;
+ font-family: inherit;
+ }
+ .dojoxGrid input {
+ }
+ .dojoxGrid select {
+ }
+ .dojoxGrid textarea {
+ }
+ #controls {
+ padding: 6px 0;
+ }
+ #grid {
+ width: 850px;
+ height: 350px;
+ border: 1px solid silver;
+ }
+</style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.data.ItemFileWriteStore");
+ dojo.require("dojo.parser");
+ </script>
+
+ <script type="text/javascript">
+ function getRow(inRowIndex){
+ return ' ' + inRowIndex;
+ }
+
+ var layoutCountries = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { field: 0, width: 'auto' },
+ { width: 8 }
+ ]]}
+ ];
+
+ removeItem = function() {
+ // Removes the first item in the model from the store
+ // Grid should reflect removal of the first item and items should be re-indexed
+ jsonStore.deleteItem(dataModel.data[0].__dojo_data_item);
+ }
+
+ var i = 0;
+ addItem = function() {
+ grid.addRow({name: "country"+(i++), type: "country"});
+ }
+ addItemToStore = function() {
+ // Adds a new item to the store
+ // Grid should reflect the new item.
+ jsonStore.newItem({name: "country"+(i++), type: "country"});
+ }
+ </script>
+</head>
+<body class="tundra">
+<h2>
+ dojox.Grid Basic Editing test
+</h2>
+<div id="controls">
+ <button onclick="grid.refresh()">Refresh</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="dataModel.clearData(true)">Clear Data (Model)</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="dataModel.refresh()">Refresh (Model)</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="grid.edit.focusEditor()">Focus Editor</button>
+ <button onclick="grid.focus.next()">Next Focus</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="addItem()">Add</button>
+ <button onclick="grid.removeSelectedRows()">Remove</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="jsonStore.revert()">Revert (Store)</button>
+ <button onclick="removeItem()">Remove (Store)</button>
+ <button onclick="addItemToStore()">Add (Store)</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="grid.edit.apply()">Apply</button>
+ <button onclick="grid.edit.cancel()">Cancel</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button>&nbsp;
+</div>
+<span dojoType="dojo.data.ItemFileWriteStore"
+ jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+</span>
+<span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel"
+ rowsPerPage="20"
+ store="jsonStore"
+ query="{ name : '*' }">
+</span>
+<div id="grid" jsId="grid" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel" structure="layoutCountries">
+</div>
+<span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel2"
+ rowsPerPage="20"
+ store="jsonStore"
+ query="{ name : '*' }">
+</span>
+<div id="grid2" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel2" structure="layoutCountries">
+</div>
+</body>
+</html>
+
+
+
diff --git a/includes/js/dojox/grid/tests/test_dojo_data_empty.html b/includes/js/dojox/grid/tests/test_dojo_data_empty.html
new file mode 100644
index 0000000..3096491
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_dojo_data_empty.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>dojox.Grid with Dojo.Data via binding</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../../../dojo/resources/dojo.css";
+ @import "../_grid/Grid.css";
+ #grid {
+ width: 65em;
+ height: 25em;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.data.ItemFileWriteStore");
+ dojo.require("dojo.parser");
+ dojo.require("dijit.form.Button");
+ </script>
+ <script type="text/javascript">
+ function getRow(inRowIndex){
+ return ' ' + inRowIndex;
+ }
+
+ var layoutCountries = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { name: "field 0", field: 0, width: 8 },
+ { name: "field 1", width: 8 }
+ ]]}
+ ];
+
+ var emptyData = { identifier: 'name', label: 'name', items: []};
+ var jsonStore = new dojo.data.ItemFileWriteStore({data: emptyData});
+ var numItems = 0;
+ </script>
+</head>
+<body class="tundra">
+ <h5>dojox.Grid using initially-empty Dojo.Data write stores and then adding an item. Item should show up correctly (no "?"s) when added.</h5>
+ <br>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel"
+ rowsPerPage="20"
+ store="jsonStore" count="0">
+ </span>
+ <div id="grid" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel" structure="layoutCountries">
+ </div>
+ <button dojoType="dijit.form.Button">
+ <script type="dojo/method" event="onClick">
+ numItems++;
+ jsonStore.newItem({name: numItems + "-person Land", type: "city", population: numItems});
+ </script>
+ Add Item
+ </button>
+</body>
+</html> \ No newline at end of file
diff --git a/includes/js/dojox/grid/tests/test_dojo_data_model.html b/includes/js/dojox/grid/tests/test_dojo_data_model.html
new file mode 100644
index 0000000..fb8e200
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_dojo_data_model.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid with Dojo.Data via binding</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../../../dojo/resources/dojo.css";
+ @import "../_grid/tundraGrid.css";
+
+ #grid, #grid2 {
+ width: 65em;
+ height: 25em;
+ padding: 1px;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.data.ItemFileReadStore");
+ dojo.require("dojox.data.CsvStore");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript">
+ function getRow(inRowIndex){
+ return ' ' + inRowIndex;
+ }
+
+ var layoutMovies = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { field: "Title", width: 'auto' },
+ { field: "Year", width: 5 },
+ { field: "Producer", width: 20 }
+ ]]}
+ ];
+
+ var layoutCountries = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { field: 0, width: 'auto' },
+ { width: 8 }
+ ]]}
+ ];
+ </script>
+</head>
+<body class="tundra">
+ <h5>dojox.Grid using Dojo.Data stores via simple binding</h5>
+ <span dojoType="dojox.data.CsvStore"
+ jsId="csvStore" url="support/movies.csv">
+ </span>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel"
+ store="csvStore"
+ rowsPerPage="5"
+ query="{ Title: '*' }"
+ clientSort="true">
+ </span>
+ <div id="grid" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel" structure="layoutMovies">
+ </div>
+
+ <span dojoType="dojo.data.ItemFileReadStore"
+ jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+ </span>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel2"
+ rowsPerPage="20"
+ store="jsonStore"
+ query="{ name : '*' }">
+ </span>
+ <div id="grid2" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel2" structure="layoutCountries">
+ </div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_dojo_data_model_EmptyResultSet.html b/includes/js/dojox/grid/tests/test_dojo_data_model_EmptyResultSet.html
new file mode 100644
index 0000000..8a9048a
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_dojo_data_model_EmptyResultSet.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid with Dojo.Data via binding</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../../../dojo/resources/dojo.css";
+ @import "../_grid/tundraGrid.css";
+
+ #grid {
+ width: 65em;
+ height: 25em;
+ padding: 1px;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.data.ItemFileReadStore");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript">
+ function getRow(inRowIndex){
+ return ' ' + inRowIndex;
+ }
+
+ var layoutCountries = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { name: "field 0", field: 0, width: 8 },
+ { name: "field 1", width: 8 }
+ ]]}
+ ];
+ </script>
+</head>
+<body class="tundra">
+ <h5>dojox.Grid using Dojo.Data stores where a query returns no results. No errors should be reported in Firebug and the grid should be empty</h5>
+ <br>
+ <span dojoType="dojo.data.ItemFileReadStore"
+ jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+ </span>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel"
+ rowsPerPage="20"
+ store="jsonStore"
+ query="{ noSuchAttr : '*' }">
+ </span>
+ <div id="grid" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel" structure="layoutCountries">
+ </div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_dojo_data_model_multiStores.html b/includes/js/dojox/grid/tests/test_dojo_data_model_multiStores.html
new file mode 100644
index 0000000..46554e3
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_dojo_data_model_multiStores.html
@@ -0,0 +1,291 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid with Dojo.Data via binding. Multiple Store implementations.</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../../../dijit/themes/tundra/tundra.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+ @import "../_grid/tundraGrid.css";
+
+ #grid, #grid2, #grid3, #grid4, #grid5, #grid6{
+ width: 65em;
+ height: 25em;
+ padding: 1px;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.data.ItemFileReadStore");
+ dojo.require("dojox.data.CsvStore");
+ dojo.require("dojox.data.XmlStore");
+ dojo.require("dojox.data.FlickrStore");
+ dojo.require("dojox.data.OpmlStore");
+ dojo.require("dojox.data.HtmlStore");
+ dojo.require("dojo.parser");
+ </script>
+
+ <script type="text/javascript">
+ function getRow(inRowIndex){
+ return ' ' + inRowIndex;
+ }
+
+ var formatHref = function(attribute, rowIndex) {
+ model = dataModel4;
+ if(!model)
+ return "?";
+ var value = model.getRow(rowIndex);
+ if(value && value[attribute])
+ return "<a href=\"" + value[attribute] + "\" target=\"_blank\">Image Link</a>";
+ return "";
+ }
+
+ var layoutMovies = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { field: "Title", width: 'auto' },
+ { field: "Year", width: 5 },
+ { field: "Producer", width: 20 }
+ ]]}
+ ];
+
+ var layoutCountries = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { field: 0, width: 'auto' },
+ { width: 8 }
+ ]]}
+ ];
+
+ var layoutBooks = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { field: "title", width: 'auto' },
+ { field: "isbn", width: '8' }
+ ]]}
+ ];
+
+ //Lay out the Flickr data so one column is a URL. This makes use of the
+ //get function of a cell.
+ var layoutFlickrData = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { name: "Title", field: "title", width: 'auto' },
+ { name: "Image URL", field: "imageUrl", width: '15', get: dojo.partial(formatHref, "imageUrl")}
+ ]]}
+ ];
+
+ var layoutOpmlData = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { name: 'Name', field: 'text', width: 'auto'},
+ { name: 'Type', field: 'type', width: '8' }
+ ]]}
+ ];
+
+ var layoutHtmlTable = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { name: 'Column 1', field: 'Column 1', width: 'auto'},
+ { name: 'Column 2', field: 'Column 2', width: 'auto'},
+ { name: 'Column 3', field: 'Column 3', width: 'auto'},
+ { name: 'Column 4', field: 'Column 4', width: 'auto'}
+ ]]}
+ ];
+ </script>
+</head>
+<body class="tundra">
+ <h1>dojox.Grid using Dojo.Data stores via simple binding with multiple store implementations.</h1>
+ <p>
+ This page demonstrates the Grid can display data accessed by dojo.data implementing Datastores.
+ Each of the datastores used stores data in a different format, and as this test and demonstration
+ page shows, the logic for rendering the data is virtually identical. You define your source store,
+ you define the model for accessing the data, which is ij this case the dojox.grid.data.DojoData model
+ and then you define the layout, which maps the data attribute names to columns in the grid. You can
+ even perform cusomization of what is displayed, as demonstrated in the dojox.data.FlickrStore layout.
+ The image url is displayed as a clickable link that opens a new page.
+ </p>
+ <p>
+ The choice of stores used were ones that did not require back end services to function for sake of
+ simplicity. There is no reason that dojox.data.QueryReadStore could not be used with grid as well,
+ it just requires a back end service to send it the query results.
+ </p>
+ <p><b>Stores used:</b></p>
+ <ul>
+ <li>dojo.data.ItemFileReadStore</li>
+ <li>dojox.data.CvsStore</li>
+ <li>dojox.data.XmlStore</li>
+ <li>dojox.data.FlickrStore</li>
+ <li>dojox.data.OpmlStore</li>
+ <li>dojox.data.HtmlTableStore</li>
+ </ul>
+
+ <h2>dojo.data.ItemFileReadStore:</h2>
+ <i>Displays a list of countries through ItemFileReadStore format.</i>
+ <span dojoType="dojo.data.ItemFileReadStore"
+ jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+ </span>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel"
+ rowsPerPage="20"
+ store="jsonStore"
+ query="{ name : '*' }">
+ </span>
+ <div id="grid" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel" structure="layoutCountries">
+ </div>
+
+
+ <h2>dojox.data.CsvStore:</h2>
+ <i>Displays a list of movies that were stored in CSV format.</i>
+ <span dojoType="dojox.data.CsvStore"
+ jsId="csvStore" url="support/movies.csv">
+ </span>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel2"
+ store="csvStore"
+ rowsPerPage="5"
+ query="{ Title: '*' }"
+ clientSort="true">
+ </span>
+ <div id="grid2" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel2" structure="layoutMovies">
+
+ </div>
+
+ <h2>dojox.data.XmlStore:</h2>
+ <i>Displays a list of books that were stored in XML format.</i>
+ <span dojoType="dojox.data.XmlStore"
+ jsId="xmlStore" url="support/books.xml">
+ </span>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel3"
+ rowsPerPage="5"
+ store="xmlStore"
+ query="{ title : '*' }">
+ </span>
+ <div id="grid3" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel3" structure="layoutBooks">
+ </div>
+
+
+ <h2>dojox.data.FlickrStore:</h2>
+ <i>Displays Flickr imformation on 3DNY (Dojo Developer Days, New York) from the flickr public photo feed, accessed via the FlickrStore dojo.data implementation.</i>
+ <span dojoType="dojox.data.FlickrStore"
+ jsId="flickrStore">
+ </span>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel4"
+ rowsPerPage="5"
+ store="flickrStore"
+ query="{ tags : '3dny' }">
+ </span>
+ <div id="grid4" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel4" structure="layoutFlickrData">
+ </div>
+
+
+ <h2>dojox.data.OpmlStore:</h2>
+ <i>Scans an Opml based document for all items of type 'country'</i>
+ <span dojoType="dojox.data.OpmlStore"
+ jsId="opmlStore" url="support/geography.xml">
+ </span>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel5"
+ rowsPerPage="5"
+ store="opmlStore"
+ query="{ type : 'country' }"
+ queryOptions="{deep: true}"
+ sortFields="[ { attribute : 'text' } ]">
+ </span>
+ <div id="grid5" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel5" structure="layoutOpmlData">
+ </div>
+
+
+ <h2>dojox.data.HtmlStore:</h2>
+ <i>Loads the grid from an HTML Table.</i>
+ <span dojoType="dojox.data.HtmlStore"
+ jsId="htmlStore" dataId="tableExample">
+ </span>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel6"
+ rowsPerPage="5"
+ store="htmlStore"
+ query="{}">
+ </span>
+ <div id="grid6" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel6" structure="layoutHtmlTable">
+ </div>
+
+ <!--
+ Inline data table to be displayed bu the grid!
+ This is accessed via the dojox.data.HtmlTableStore
+ -->
+ <table id="tableExample" style="display: none;">
+ <thead>
+ <tr>
+ <th>Column 1</th>
+ <th>Column 2</th>
+ <th>Column 3</th>
+ <th>Column 4</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>This</td>
+ <td>is</td>
+ <td></td>
+ <td>empty in column 3</td>
+ </tr>
+ <tr>
+ <td>This</td>
+ <td>is</td>
+ <td>a</td>
+ <td>value</td>
+ </tr>
+ <tr>
+ <td>Who?</td>
+ <td>What?</td>
+ <td>When?</td>
+ <td>Where?</td>
+ </tr>
+ <tr>
+ <td>She</td>
+ <td>sells</td>
+ <td>sea</td>
+ <td>shells</td>
+ </tr>
+ </tbody>
+ </table>
+</body>
+</html>
+
+
diff --git a/includes/js/dojox/grid/tests/test_dojo_data_model_processError.html b/includes/js/dojox/grid/tests/test_dojo_data_model_processError.html
new file mode 100644
index 0000000..4130043
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_dojo_data_model_processError.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid with Dojo.Data model with trapping of data store errors.</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../../../dijit/themes/tundra/tundra.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+ @import "../_grid/tundraGrid.css";
+
+ #grid{
+ width: 65em;
+ height: 25em;
+ padding: 1px;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojox.data.CsvStore");
+ dojo.require("dojo.parser");
+ </script>
+
+ <script type="text/javascript">
+ var layoutMovies = [
+ { cells: [[
+ { name: "Title", field: "Title", width: 'auto' },
+ { name: "Year", field: "Year", width: 5 },
+ { name: "Producer", field: "Producer", width: 20 }
+ ]]}
+ ];
+
+ </script>
+</head>
+<body class="tundra">
+ <h1>dojox.Grid using Dojo.Data stores via simple binding</h1>
+
+ <h2>dojox.data.CsvStore:</h2>.
+ <i>This grid does not load data. The data store references a non-existent URL on purpose. It should trigger a failure that we catch and display in an alert</i>
+ <span dojoType="dojox.data.CsvStore"
+ jsId="csvStore" url="support/NoSuchMovieFile.csv">
+ </span>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel"
+ store="csvStore"
+ rowsPerPage="5"
+ query="{ Title: '*' }"
+ clientSort="true">
+ <!--
+ This uses the dojo/connect API to link to the processError handler of the model.
+ It allows a declarative way to hook to the handler on the model.
+ -->
+ <script type="dojo/connect" event="processError" args="error, request">
+ alert("Error was encountered when store was queried: " + dojo.toJson(error, true));
+ </script>
+ </span>
+ <div id="grid" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel" structure="layoutMovies">
+ </div>
+</body>
+</html>
+
+
diff --git a/includes/js/dojox/grid/tests/test_dojo_data_notification.html b/includes/js/dojox/grid/tests/test_dojo_data_notification.html
new file mode 100644
index 0000000..f44c987
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_dojo_data_notification.html
@@ -0,0 +1,114 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid with Dojo.Data via binding</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/tundraGrid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/themes/tundra/tundra.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+
+ #grid, #grid2, #grid3 {
+ width: 65em;
+ height: 25em;
+ padding: 1px;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojox.data.CsvStore");
+ dojo.require("dojo.data.ItemFileWriteStore");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript">
+ function getRow(inRowIndex){
+ return ' ' + inRowIndex;
+ }
+
+ var iEditor = dojox.grid.editors.Input;
+ var layoutMovies = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { field: "Title", editor: iEditor, width: 'auto' },
+ { field: "Year", editor: iEditor, width: 5 },
+ { field: "Producer", editor: iEditor, width: 20 }
+ ]]}
+ ];
+
+ var layoutCountries = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ { cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+ // view 2
+ { cells: [[
+ { field: "name", name: "Name", width: 'auto' },
+ { field: "type", name: "Type", editor: iEditor, width: 'auto' },
+ ]]}
+ ];
+ </script>
+</head>
+<body class="tundra">
+ <h1>dojox.Grid using Dojo.Data stores via simple binding</h1>
+ <!--
+ <br>
+ <span dojoType="dojox.data.CsvStore"
+ jsId="csvStore" url="support/movies.csv">
+ </span>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel"
+ store="csvStore"
+ rowsPerPage="5"
+ query="{ Title: '*' }"
+ clientSort="true">
+ </span>
+ <div id="grid" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel" structure="layoutMovies">
+ </div>
+ -->
+ <br>
+ <h3>Update some of the types</h3>
+ <button onclick="updateCountryTypes();">Go!</button>
+ <script>
+ function updateCountryTypes(){
+ // get everything starting with "A"
+ jsonStore.fetch({
+ query: { name: "A*" },
+ onComplete: function(items, result){
+ // change 'em!
+ dojo.forEach(items, function(item){
+ jsonStore.setValue(item, "type", "thinger");
+ // console.debug(item);
+ });
+ }
+ });
+ }
+ </script>
+
+ <span dojoType="dojo.data.ItemFileWriteStore"
+ jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+ </span>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel2"
+ rowsPerPage="20"
+ store="jsonStore"
+ clientSort="true"
+ query="{ name : '*' }">
+ </span>
+ <div id="grid2" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel2" structure="layoutCountries">
+ </div>
+
+ <div id="grid3" dojoType="dojox.Grid" elasticView="2"
+ model="dataModel2" structure="layoutCountries">
+ </div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_edit.html b/includes/js/dojox/grid/tests/test_edit.html
new file mode 100644
index 0000000..7ae1fdb
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_edit.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Test dojox.Grid Editing</title>
+<style>
+ @import "../_grid/Grid.css";
+ body {
+ font-family: Tahoma, Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ }
+ .dojoxGrid-row-editing td {
+ background-color: #F4FFF4;
+ }
+ .dojoxGrid input, .dojoxGrid select, .dojoxGrid textarea {
+ margin: 0;
+ padding: 0;
+ border-style: none;
+ width: 100%;
+ font-size: 100%;
+ font-family: inherit;
+ }
+ .dojoxGrid input {
+ }
+ .dojoxGrid select {
+ }
+ .dojoxGrid textarea {
+ }
+ #controls {
+ padding: 6px 0;
+ }
+ #grid {
+ width: 850px;
+ height: 350px;
+ border: 1px solid silver;
+ }
+</style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+ <!--<script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>-->
+ <!-- Debugging -->
+ <script type="text/javascript" src="../_grid/lib.js"></script>
+ <script type="text/javascript" src="../_grid/drag.js"></script>
+ <script type="text/javascript" src="../_grid/scroller.js"></script>
+ <script type="text/javascript" src="../_grid/builder.js"></script>
+ <script type="text/javascript" src="../_grid/cell.js"></script>
+ <script type="text/javascript" src="../_grid/layout.js"></script>
+ <script type="text/javascript" src="../_grid/rows.js"></script>
+ <script type="text/javascript" src="../_grid/focus.js"></script>
+ <script type="text/javascript" src="../_grid/selection.js"></script>
+ <script type="text/javascript" src="../_grid/edit.js"></script>
+ <script type="text/javascript" src="../_grid/view.js"></script>
+ <script type="text/javascript" src="../_grid/views.js"></script>
+ <script type="text/javascript" src="../_grid/rowbar.js"></script>
+ <script type="text/javascript" src="../_grid/publicEvents.js"></script>
+ <script type="text/javascript" src="../VirtualGrid.js"></script>
+ <script type="text/javascript" src="../_data/fields.js"></script>
+ <script type="text/javascript" src="../_data/model.js"></script>
+ <script type="text/javascript" src="../_data/editors.js"></script>
+ <script type="text/javascript" src="../Grid.js"></script>
+ <script type="text/javascript">
+ // ==========================================================================
+ // Create a data model
+ // ==========================================================================
+ data = [
+ [ 0, false, "new", 'But are not followed by two hexadecimal', 29.91, 10, false ],
+ [ 1, false, "new", 'Because a % sign always indicates', 9.33, -5, false ],
+ [ 1, false, "read", 'Signs can be selectively', 19.34, 0, true ],
+ [ 2, false, "read", 'However the reserved characters', 15.63, 0, true ],
+ [ 0, false, "replied", 'It is therefore necessary', 24.22, 5.50, true ],
+ [ 1, false, "replied", 'To problems of corruption by', 9.12, -3, true ],
+ [ 2, false, "replied", 'Which would simply be awkward in', 12.15, -4, false ]
+ ];
+ var rows = 10000;
+ for(var i=0, l=data.length; i<rows-l; i++){
+ data.push(data[i%l].slice(0));
+ }
+ model = new dojox.grid.data.Table(null, data);
+ // ==========================================================================
+ // Tie some UI to the data model
+ // ==========================================================================
+ model.observer(this);
+ modelChange = function() {
+ dojo.byId("rowCount").innerHTML = 'Row count: ' + model.count;
+ }
+ // ==========================================================================
+ // Custom formatter
+ // ==========================================================================
+ formatMoney = function(inDatum) {
+ return isNaN(inDatum) ? '...' : '$' + parseFloat(inDatum).toFixed(2);
+ }
+ // ==========================================================================
+ // Grid structure
+ // ==========================================================================
+ statusCell = { field: 2, name: 'Status', styles: 'text-align: center;', editor: dojox.grid.editors.Select, options: [ "new", "read", "replied" ] };
+ gridLayout = [{
+ type: 'dojox.GridRowView', width: '20px'
+ },{
+ defaultCell: { width: 8, editor: dojox.grid.editors.Input, styles: 'text-align: right;' },
+ rows: [[
+ { name: 'Id', width: 3, get: function(inRowIndex) { return inRowIndex+1;} },
+ { name: 'Priority', styles: 'text-align: center;', editor: dojox.grid.editors.Select, options: ["normal", "note", "important"], values: [0, 1, 2], formatter: function(inDatum) { return this.options[inDatum]}},
+ { name: 'Mark', width: 3, styles: 'text-align: center;', editor: dojox.grid.editors.Bool },
+ statusCell,
+ { name: 'Message', styles: '', width: '100%' },
+ { name: 'Amount', formatter: formatMoney },
+ { name: 'Amount', field: 4, formatter: formatMoney }
+ ]]
+ },{
+ defaultCell: { width: 4, editor: dojox.grid.editors.Input, styles: 'text-align: right;' },
+ rows: [[
+ { name: 'Mark', width: 3, field: 1, styles: 'text-align: center;', editor: dojox.grid.editors.Bool},
+ statusCell,
+ { name: 'Amount', field: 4, formatter: formatMoney},
+ { name: 'Detail', value: 'Detail'}
+ ]]
+ }];
+ // ==========================================================================
+ // UI Action
+ // ==========================================================================
+ addRow = function(){
+ grid.addRow([ "normal", false, "new", 'Now is the time for all good men to come to the aid of their party.', 99.99, 9.99, false ]);
+ }
+</script>
+</head>
+<body>
+<h2>
+ dojox.Grid Basic Editing test
+</h2>
+<div id="controls">
+ <button onclick="grid.refresh()">Refresh</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="grid.edit.focusEditor()">Focus Editor</button>
+ <button onclick="grid.focus.next()">Next Focus</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="addRow()">Add Row</button>
+ <button onclick="grid.removeSelectedRows()">Remove</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="grid.edit.apply()">Apply</button>
+ <button onclick="grid.edit.cancel()">Cancel</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button>&nbsp;
+</div>
+<br />
+<div id="grid" dojoType="dojox.Grid"
+ jsId="grid"
+ model="model" structure="gridLayout"></div>
+<br />
+<div id="rowCount"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_edit_canEdit.html b/includes/js/dojox/grid/tests/test_edit_canEdit.html
new file mode 100644
index 0000000..ed4e919
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_edit_canEdit.html
@@ -0,0 +1,156 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Test dojox.Grid Editing</title>
+<style>
+ @import "../_grid/Grid.css";
+ body {
+ font-family: Tahoma, Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ }
+ .dojoxGrid-row-editing td {
+ background-color: #F4FFF4;
+ }
+ .dojoxGrid input, .dojoxGrid select, .dojoxGrid textarea {
+ margin: 0;
+ padding: 0;
+ border-style: none;
+ width: 100%;
+ font-size: 100%;
+ font-family: inherit;
+ }
+ .dojoxGrid input {
+ }
+ .dojoxGrid select {
+ }
+ .dojoxGrid textarea {
+ }
+ #controls {
+ padding: 6px 0;
+ }
+ #grid {
+ width: 850px;
+ height: 350px;
+ border: 1px solid silver;
+ }
+</style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+ <!--<script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>-->
+ <!-- Debugging -->
+ <script type="text/javascript" src="../_grid/lib.js"></script>
+ <script type="text/javascript" src="../_grid/drag.js"></script>
+ <script type="text/javascript" src="../_grid/scroller.js"></script>
+ <script type="text/javascript" src="../_grid/builder.js"></script>
+ <script type="text/javascript" src="../_grid/cell.js"></script>
+ <script type="text/javascript" src="../_grid/layout.js"></script>
+ <script type="text/javascript" src="../_grid/rows.js"></script>
+ <script type="text/javascript" src="../_grid/focus.js"></script>
+ <script type="text/javascript" src="../_grid/selection.js"></script>
+ <script type="text/javascript" src="../_grid/edit.js"></script>
+ <script type="text/javascript" src="../_grid/view.js"></script>
+ <script type="text/javascript" src="../_grid/views.js"></script>
+ <script type="text/javascript" src="../_grid/rowbar.js"></script>
+ <script type="text/javascript" src="../_grid/publicEvents.js"></script>
+ <script type="text/javascript" src="../VirtualGrid.js"></script>
+ <script type="text/javascript" src="../_data/fields.js"></script>
+ <script type="text/javascript" src="../_data/model.js"></script>
+ <script type="text/javascript" src="../_data/editors.js"></script>
+ <script type="text/javascript" src="../Grid.js"></script>
+ <script type="text/javascript">
+ // ==========================================================================
+ // Create a data model
+ // ==========================================================================
+ data = [
+ [ "normal", false, "new", 'But are not followed by two hexadecimal', 29.91, 10, false ],
+ [ "important", false, "new", 'Because a % sign always indicates', 9.33, -5, false ],
+ [ "important", false, "read", 'Signs can be selectively', 19.34, 0, true ],
+ [ "note", false, "read", 'However the reserved characters', 15.63, 0, true ],
+ [ "normal", false, "replied", 'It is therefore necessary', 24.22, 5.50, true ],
+ [ "important", false, "replied", 'To problems of corruption by', 9.12, -3, true ],
+ [ "note", false, "replied", 'Which would simply be awkward in', 12.15, -4, false ]
+ ];
+ var rows = 10000;
+ for(var i=0, l=data.length; i<rows-l; i++){
+ data.push(data[i%l].slice(0));
+ }
+ model = new dojox.grid.data.Table(null, data);
+ // ==========================================================================
+ // Tie some UI to the data model
+ // ==========================================================================
+ model.observer(this);
+ modelChange = function() {
+ dojo.byId("rowCount").innerHTML = 'Row count: ' + model.count;
+ }
+ // ==========================================================================
+ // Custom formatter
+ // ==========================================================================
+ formatMoney = function(inDatum) {
+ return isNaN(inDatum) ? '...' : '$' + parseFloat(inDatum).toFixed(2);
+ }
+ // ==========================================================================
+ // Grid structure
+ // ==========================================================================
+ statusCell = { field: 2, name: 'Status', styles: 'text-align: center;', editor: dojox.grid.editors.Select, options: [ "new", "read", "replied" ] };
+ gridLayout = [{
+ type: 'dojox.GridRowView', width: '20px'
+ },{
+ defaultCell: { width: 8, editor: dojox.grid.editors.Input, styles: 'text-align: right;' },
+ rows: [[
+ { name: 'Id', width: 3, get: function(inRowIndex) { return inRowIndex+1;} },
+ { name: 'Priority', styles: 'text-align: center;', editor: dojox.grid.editors.Select, options: ["normal", "note", "important"]},
+ { name: 'Mark', width: 3, styles: 'text-align: center;', editor: dojox.grid.editors.Bool },
+ statusCell,
+ { name: 'Message', styles: '', width: '100%' },
+ { name: 'Amount', formatter: formatMoney },
+ { name: 'Amount', field: 4, formatter: formatMoney }
+ ]]
+ },{
+ defaultCell: { width: 4, editor: dojox.grid.editors.Input, styles: 'text-align: right;' },
+ rows: [[
+ { name: 'Mark', width: 3, field: 1, styles: 'text-align: center;', editor: dojox.grid.editors.Bool},
+ statusCell,
+ { name: 'Amount', field: 4, formatter: formatMoney},
+ { name: 'Detail', value: 'Detail'}
+ ]]
+ }];
+ // ==========================================================================
+ // UI Action
+ // ==========================================================================
+ addRow = function(){
+ grid.addRow([ "normal", false, "new", 'Now is the time for all good men to come to the aid of their party.', 99.99, 9.99, false ]);
+ }
+
+ dojo.addOnLoad(function() {
+ // simple canEdit logic
+ grid.canEdit = function(inCell, inRowIndex) {
+ return !(inCell.index > 1 && inCell.index < 5)
+ }
+ });
+</script>
+</head>
+<body>
+<h2>
+ dojox.Grid Basic Editing test
+</h2>
+<div id="controls">
+ <button onclick="grid.refresh()">Refresh</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="grid.edit.focusEditor()">Focus Editor</button>
+ <button onclick="grid.focus.next()">Next Focus</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="addRow()">Add Row</button>
+ <button onclick="grid.removeSelectedRows()">Remove</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="grid.edit.apply()">Apply</button>
+ <button onclick="grid.edit.cancel()">Cancel</button>&nbsp;&nbsp;&nbsp;
+ <button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button>&nbsp;
+</div>
+<br />
+<div id="grid" dojoType="dojox.Grid"
+ jsId="grid"
+ model="model" structure="gridLayout"></div>
+<br />
+<div id="rowCount"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_edit_dijit.html b/includes/js/dojox/grid/tests/test_edit_dijit.html
new file mode 100644
index 0000000..484c7e5
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_edit_dijit.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>Test dojox.Grid Editing</title>
+ <style type="text/css">
+ @import "../_grid/tundraGrid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/themes/tundra/tundra.css";
+ @import "../../../dijit/themes/tundra/tundra_rtl.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+ #controls button {
+ margin-left: 10px;
+ }
+ #grid {
+ width: 850px;
+ height: 350px;
+ border: 1px solid silver;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+
+ // ==========================================================================
+ // Create a data model
+ // ==========================================================================
+
+ s = (new Date()).getTime();
+
+ data = [
+ [ "normal", false, "new", 'But are not followed by two hexadecimal', 29.91, 10, false, s],
+ [ "important", false, "new", 'Because a % sign always indicates', 9.33, -5, false, s ],
+ [ "important", false, "read", 'Signs can be selectively', 19.34, 0, true, s ],
+ [ "note", false, "read", 'However the reserved characters', 15.63, 0, true, s ],
+ [ "normal", false, "replied", 'It is therefore necessary', 24.22, 5.50, true, s ],
+ [ "important", false, "replied", 'To problems of corruption by', 9.12, -3, true, s ],
+ [ "note", false, "replied", 'Which would simply be awkward in', 12.15, -4, false, s ]
+ ];
+ var rows = 100;
+ for(var i=0, l=data.length; i<rows; i++){
+ data.push(data[i%l].slice(0));
+ }
+ model = new dojox.grid.data.Table(null, data);
+ // ==========================================================================
+ // Tie some UI to the data model
+ // ==========================================================================
+ model.observer(this);
+ modelChange = function(){
+ dojo.byId("rowCount").innerHTML = 'Row count: ' + model.count;
+ }
+ /*
+ modelInsertion = modelDatumChange = function(a1, a2, a3){
+ console.debug(a1, a2, a3);
+ }
+ */
+ // ==========================================================================
+ // Custom formatters
+ // ==========================================================================
+ formatCurrency = function(inDatum){
+ return isNaN(inDatum) ? '...' : dojo.currency.format(inDatum, this.constraint);
+ }
+ formatDate = function(inDatum){
+ return dojo.date.locale.format(new Date(inDatum), this.constraint);
+ }
+ // ==========================================================================
+ // Grid structure
+ // ==========================================================================
+ statusCell = {
+ field: 2, name: 'Status',
+ styles: 'text-align: center;',
+ editor: dojox.grid.editors.Select,
+ options: [ "new", "read", "replied" ]
+ };
+
+ gridLayout = [{
+ type: 'dojox.GridRowView', width: '20px'
+ },{
+ defaultCell: { width: 8, editor: dojox.grid.editors.Input, styles: 'text-align: right;' },
+ rows: [[
+ { name: 'Id',
+ get: function(inRowIndex) { return inRowIndex+1;},
+ editor: dojox.grid.editors.Dijit,
+ editorClass: "dijit.form.NumberSpinner" },
+ { name: 'Date', width: 10, field: 7,
+ editor: dojox.grid.editors.DateTextBox,
+ formatter: formatDate,
+ constraint: {formatLength: 'long', selector: "date"}},
+ { name: 'Priority', styles: 'text-align: center;', field: 0,
+ editor: dojox.grid.editors.ComboBox,
+ options: ["normal", "note", "important"], width: 10},
+ { name: 'Mark', width: 3, styles: 'text-align: center;',
+ editor: dojox.grid.editors.CheckBox},
+ statusCell,
+ { name: 'Message', styles: '', width: '100%',
+ editor: dojox.grid.editors.Editor, editorToolbar: true },
+ { name: 'Amount', formatter: formatCurrency, constraint: {currency: 'EUR'},
+ editor: dojox.grid.editors.Dijit, editorClass: "dijit.form.CurrencyTextBox" },
+ { name: 'Amount', field: 4, formatter: formatCurrency, constraint: {currency: 'EUR'},
+ editor: dojox.grid.editors.Dijit, editorClass: "dijit.form.HorizontalSlider", width: 10}
+ ]]
+ }];
+ // ==========================================================================
+ // UI Action
+ // ==========================================================================
+ addRow = function(){
+ grid.addRow([
+ "normal", false, "new",
+ 'Now is the time for all good men to come to the aid of their party.',
+ 99.99, 9.99, false
+ ]);
+ }
+ </script>
+</head>
+<body>
+ <h1>dojox.Grid Basic Editing test</h1>
+ <br />
+ <div id="controls">
+ <button onclick="grid.refresh()">Refresh</button>
+ <button onclick="grid.edit.focusEditor()">Focus Editor</button>
+ <button onclick="grid.focus.next()">Next Focus</button>
+ <button onclick="addRow()">Add Row</button>
+ <button onclick="grid.removeSelectedRows()">Remove</button>
+ <button onclick="grid.edit.apply()">Apply</button>
+ <button onclick="grid.edit.cancel()">Cancel</button>
+ <button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button>
+ </div>
+ <br />
+ <div id="grid" jsId="grid" dojoType="dojox.Grid" model="model" structure="gridLayout"></div>
+ <br />
+ <div id="rowCount"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_events.html b/includes/js/dojox/grid/tests/test_events.html
new file mode 100644
index 0000000..8ea61a4
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_events.html
@@ -0,0 +1,174 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>Test dojox.Grid Events</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ body,td,th {
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ #grid {
+ border: 1px solid;
+ border-top-color: #F6F4EB;
+ border-right-color: #ACA899;
+ border-bottom-color: #ACA899;
+ border-left-color: #F6F4EB;
+ }
+ #grid {
+ width: 50em;
+ height: 20em;
+ padding: 1px;
+ overflow: hidden;
+ font-size: small;
+ }
+ h3 {
+ margin: 10px 0 2px 0;
+ }
+ .fade {
+ /*background-image:url(images/fade.gif);*/
+ }
+ .no-fade {
+ /*background-image: none;*/
+ }
+ #eventGrid {
+ float: right;
+ font-size: small;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript">
+ // events to track
+ var eventRows = [
+ { name: 'onCellClick' },
+ { name: 'onRowClick', properties: ['rowIndex'] },
+ { name: 'onCellDblClick' },
+ { name: 'onRowDblClick', properties: ['rowIndex'] },
+ { name: 'onCellMouseOver' },
+ { name: 'onCellMouseOut' },
+ { name: 'onCellMouseDown' },
+ { name: 'onRowMouseOver' },
+ { name: 'onRowMouseOut' },
+ { name: 'onRowMouseDown' },
+ { name: 'onHeaderCellClick' },
+ { name: 'onHeaderClick', properties: ['rowIndex'] },
+ { name: 'onHeaderCellDblClick' },
+ { name: 'onHeaderDblClick', properties: ['rowIndex'] },
+ { name: 'onHeaderCellMouseOver' },
+ { name: 'onHeaderCellMouseOut' },
+ { name: 'onHeaderCellMouseDown' },
+ { name: 'onHeaderMouseOver' },
+ { name: 'onHeaderMouseOut' },
+ { name: 'onKeyDown', properties: ['keyCode'] },
+ { name: 'onCellContextMenu' },
+ { name: 'onRowContextMenu', properties: ['rowIndex'] },
+ { name: 'onHeaderCellContextMenu' },
+ { name: 'onHeaderContextMenu', properties: ['rowIndex'] }
+ ];
+
+ getEventName = function(inRowIndex) {
+ return eventRows[inRowIndex].name;
+ };
+
+ getEventData = function(inRowIndex) {
+ var d = eventRows[inRowIndex].data;
+ var r = [];
+ if (d)
+ for (var i in d)
+ r.push(d[i]);
+ else
+ r.push('na')
+ return r.join(', ');
+ }
+
+ // grid structure for event tracking grid.
+ var eventView = {
+ noscroll: true,
+ cells: [[
+ { name: 'Event', get: getEventName, width: 12 },
+ { name: 'Data', get: getEventData, width: 10 }
+ ]]
+ }
+ var eventLayout = [ eventView ];
+
+ var fade = function(inNode) {
+ if (!inNode || !inNode.style) return;
+ var c = 150, step = 5, delay = 20;
+ var animate = function() {
+ c = Math.min(c + step, 255);
+ inNode.style.backgroundColor = "rgb(" + c + ", " + c + ", 255)";
+ if (c < 255) window.setTimeout(animate, delay);
+ }
+ animate();
+ }
+
+ // setup a fade on a row. Must do this way to avoid caching of fade gif
+ updateRowFade = function(inRowIndex) {
+ var n = eventGrid.views.views[0].getRowNode(inRowIndex);
+ fade(n);
+ }
+
+ // store data about event. By default track event.rowIndex and event.cell.index, but eventRows can specify params, which are event properties to track.
+ setEventData = function(inIndex, inEvent) {
+ var eRow = eventRows[inIndex];
+ eRow.data = {};
+ var properties = eRow.properties;
+ if (properties)
+ for (var i=0, l=properties.length, p; (p=properties[i] || i < l); i++)
+ eRow.data[p] = inEvent[p];
+ else
+ eRow.data = {
+ row: (inEvent.rowIndex != undefined ? Number(inEvent.rowIndex) : 'na'),
+ cell: (inEvent.cell && inEvent.cell.index != undefined ? inEvent.cell.index : 'na')
+ }
+ eventGrid.updateRow(inIndex);
+ updateRowFade(inIndex);
+ }
+
+ // setup grid events for all events being tracked.
+ setGridEvents = function() {
+ var makeEvent = function(inIndex, inName) {
+ return function(e) {
+ setEventData(inIndex, e);
+ dojox.VirtualGrid.prototype[inName].apply(this, arguments);
+ }
+ }
+ for (var i=0, e; (e=eventRows[i]); i++)
+ grid[e.name] = makeEvent(i, e.name);
+ }
+
+ // Grid structure
+ var layout = [// array of view objects
+ { type: 'dojox.GridRowView', width: '20px' },
+ { noscroll: true, cells: [// array of rows, a row is an array of cells
+ [{ name: "Alpha", value: '<input type="checkbox"></input>', rowSpan: 2, width: 6, styles: 'text-align:center;' }, { name: "Alpha2", value: "Alpha2" }],
+ [{ name: "Alpha3", value: "Alpha3" }]
+ ]},
+ { cells: [
+ [{ name: "Beta", value: 'simple'}, { name: "Beta2", value: "Beta2" }, { name: "Beta3", value: "Beta3" }, { name: "Beta4", value: "Beta4" }, { name: "Beta5", value: "Beta5" }],
+ [{ name: "Summary", colSpan: 5, value: 'Summary' }]
+ ]},
+ { noscroll: true, cells: [
+ [{ name: "Gamma", value: "Gamma" }, { name: "Gamma2", value: "<button>Radiate</button>", styles: 'text-align:center;' }]]
+ }];
+
+ dojo.addOnLoad(function() {
+ window["grid"] = dijit.byId("grid");
+ window["eventGrid"] = dijit.byId("eventGrid");
+ grid.rows.defaultRowHeight = 4;
+ setGridEvents();
+ eventGrid.updateRowCount(eventRows.length);
+ dojo.debug = console.log;
+ });
+ </script>
+</head>
+<body>
+<h3>dojox.Grid Event Tracking</h3>
+<div id="eventGrid" autoWidth="true" autoHeight="true" structure="eventLayout" dojoType="dojox.VirtualGrid"></div>
+<div id="grid" rowCount="100" dojoType="dojox.VirtualGrid"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_expand.html b/includes/js/dojox/grid/tests/test_expand.html
new file mode 100644
index 0000000..220c2a8
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_expand.html
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>Test dojox.Grid Expand Rows</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ .bigHello {
+ height: 110px;
+ line-height: 110px;
+ text-align: center;
+ font-weight: bold;
+ font-size: 30px;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ height: 30em;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript">
+ // grid structure
+ // a grid view is a group of columns
+
+ // a special view providing selection feedback
+ var rowBar = {type: 'dojox.GridRowView', width: '20px' };
+
+ // inRow is an array of subRows. we hide the summary subRow except for every nth row
+ function onBeforeRow(inDataIndex, inRow) {
+ inRow[1].hidden = (!this.grid || !this.grid.expandedRows || !this.grid.expandedRows[inDataIndex]);
+ }
+
+ var view = {
+ onBeforeRow: onBeforeRow,
+ cells: [
+ [
+ { name: 'Whatever', width: 4.5, get: getCheck, styles: 'text-align: center;' },
+ {name: 'Column 0'},
+ {name: 'Column 1'},
+ {name: 'Column 2'},
+ {name: 'Column 3'},
+ {name: 'Column 4'}
+ ],
+ [ { name: 'Detail', colSpan: 6, get: getDetail } ]
+ ]
+ };
+
+ // a grid structure is an array of views.
+ var structure = [ rowBar, view ];
+
+ // get can return data for each cell of the grid
+ function get(inRowIndex) {
+ return [this.index, inRowIndex].join(', ');
+ }
+
+ function getDetail(inRowIndex) {
+ if (this.grid.expandedRows[inRowIndex]) {
+ var n = (inRowIndex % 2);
+ switch (n) {
+ case 0:
+ return 'Hello World!';
+ default:
+ return '<div class="bigHello">Hello World!</div>';
+ }
+ } else
+ return '';
+ }
+
+ function toggle(inIndex, inShow) {
+ grid.expandedRows[inIndex] = inShow;
+ grid.updateRow(inIndex);
+ }
+
+ function getCheck(inRowIndex) {
+ if (!this.grid.expandedRows)
+ this.grid.expandedRows = [ ];
+ var image = (this.grid.expandedRows[inRowIndex] ? 'open.gif' : 'closed.gif');
+ var show = (this.grid.expandedRows[inRowIndex] ? 'false' : 'true')
+ return '<img src="images/' + image + '" onclick="toggle(' + inRowIndex + ', ' + show + ')" height="11" width="11">';
+ }
+
+ dojo.addOnLoad(function() {
+ window["grid"] = dijit.byId("grid");
+ });
+</script>
+</head>
+<body>
+<div class="heading">dojox.Grid Expand Row Example</div>
+
+<div id="grid" dojoType="dojox.VirtualGrid" get="get" structure="structure" rowCount="100000" autoWidth="true"></div>
+
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_grid.html b/includes/js/dojox/grid/tests/test_grid.html
new file mode 100644
index 0000000..59d18dc
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_grid.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>Test dojox.Grid Basic</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ @import "../_grid/tundraGrid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/themes/tundra/tundra.css";
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ width: 35em;
+ height: 30em;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+ <!--<script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>-->
+ <!-- Debugging -->
+ <script type="text/javascript" src="../_grid/lib.js"></script>
+ <script type="text/javascript" src="../_grid/drag.js"></script>
+ <script type="text/javascript" src="../_grid/scroller.js"></script>
+ <script type="text/javascript" src="../_grid/builder.js"></script>
+ <script type="text/javascript" src="../_grid/cell.js"></script>
+ <script type="text/javascript" src="../_grid/layout.js"></script>
+ <script type="text/javascript" src="../_grid/rows.js"></script>
+ <script type="text/javascript" src="../_grid/focus.js"></script>
+ <script type="text/javascript" src="../_grid/selection.js"></script>
+ <script type="text/javascript" src="../_grid/edit.js"></script>
+ <script type="text/javascript" src="../_grid/view.js"></script>
+ <script type="text/javascript" src="../_grid/views.js"></script>
+ <script type="text/javascript" src="../_grid/rowbar.js"></script>
+ <script type="text/javascript" src="../_grid/publicEvents.js"></script>
+ <script type="text/javascript" src="../VirtualGrid.js"></script>
+ <script type="text/javascript" src="../_data/fields.js"></script>
+ <script type="text/javascript" src="../_data/model.js"></script>
+ <script type="text/javascript" src="../_data/editors.js"></script>
+ <script type="text/javascript" src="../Grid.js"></script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ // a grid view is a group of columns
+ var view1 = {
+ cells: [[
+ {name: 'Column 0'}, {name: 'Column 1'}, {name: 'Column 2'}, {name: 'Column 3', width: "150px"}, {name: 'Column 4'}
+ ],[
+ {name: 'Column 5'}, {name: 'Column 6'}, {name: 'Column 7'}, {name: 'Column 8', field: 3, colSpan: 2}
+ ]]
+ };
+ // a grid layout is an array of views.
+ var layout = [ view1 ];
+</script>
+</head>
+<body>
+<div class="heading">dojox.Grid Basic Test</div>
+<div jsid="grid" id="grid" dojoType="dojox.Grid" model="model" structure="layout"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_grid_dlg.html b/includes/js/dojox/grid/tests/test_grid_dlg.html
new file mode 100644
index 0000000..7479e15
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_grid_dlg.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>Test dojox.Grid Basic</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+ <script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+ table { border: none; }
+
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ width: 400px;
+ height: 500px;
+ }
+ </style>
+ <!--<script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>-->
+ <!-- Debugging -->
+ <script type="text/javascript" src="../_grid/lib.js"></script>
+ <script type="text/javascript" src="../_grid/drag.js"></script>
+ <script type="text/javascript" src="../_grid/scroller.js"></script>
+ <script type="text/javascript" src="../_grid/builder.js"></script>
+ <script type="text/javascript" src="../_grid/cell.js"></script>
+ <script type="text/javascript" src="../_grid/layout.js"></script>
+ <script type="text/javascript" src="../_grid/rows.js"></script>
+ <script type="text/javascript" src="../_grid/focus.js"></script>
+ <script type="text/javascript" src="../_grid/selection.js"></script>
+ <script type="text/javascript" src="../_grid/edit.js"></script>
+ <script type="text/javascript" src="../_grid/view.js"></script>
+ <script type="text/javascript" src="../_grid/views.js"></script>
+ <script type="text/javascript" src="../_grid/rowbar.js"></script>
+ <script type="text/javascript" src="../_grid/publicEvents.js"></script>
+ <script type="text/javascript" src="../VirtualGrid.js"></script>
+ <script type="text/javascript" src="../_data/fields.js"></script>
+ <script type="text/javascript" src="../_data/model.js"></script>
+ <script type="text/javascript" src="../_data/editors.js"></script>
+ <script type="text/javascript" src="../Grid.js"></script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ // a grid view is a group of columns
+ var view1 = {
+ cells: [[
+ {name: 'Column 0'}, {name: 'Column 1'}, {name: 'Column 2'}, {name: 'Column 3', width: "150px"}, {name: 'Column 4'}
+ ],[
+ {name: 'Column 5'}, {name: 'Column 6'}, {name: 'Column 7'}, {name: 'Column 8', field: 3, colSpan: 2}
+ ]]
+ };
+ // a grid layout is an array of views.
+ var layout = [ view1 ];
+ dojo.require("dijit.Dialog");
+ dojo.require("dijit.form.Button");
+ dojo.require("dojo.parser"); // scan page for widgets and instantiate them
+
+ function openDialog() {
+ var dialog = dijit.byId('dialog');
+ dialog.show();
+ }
+</script>
+</head>
+<body>
+<div class="heading">dojox.Grid Basic Test</div>
+<button onclick="openDialog()">open</button>
+<div id="dialog" dojoType="dijit.Dialog" title="First Dialog">
+ <table>
+ <tr><td><div id="grid" dojoType="dojox.Grid" model="model" structure="layout"></div></td></tr>
+ <tr><td><button dojoType="dijit.form.Button" type="submit">close</button></td></tr>
+ </table>
+</div>
+
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_grid_headerHeight.html b/includes/js/dojox/grid/tests/test_grid_headerHeight.html
new file mode 100644
index 0000000..b9960c4
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_grid_headerHeight.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>Test dojox.Grid Basic</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ @import "../_grid/tundraGrid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/themes/tundra/tundra.css";
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ width: 65em;
+ height: 30em;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+ <!--<script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>-->
+ <!-- Debugging -->
+ <script type="text/javascript" src="../_grid/lib.js"></script>
+ <script type="text/javascript" src="../_grid/drag.js"></script>
+ <script type="text/javascript" src="../_grid/scroller.js"></script>
+ <script type="text/javascript" src="../_grid/builder.js"></script>
+ <script type="text/javascript" src="../_grid/cell.js"></script>
+ <script type="text/javascript" src="../_grid/layout.js"></script>
+ <script type="text/javascript" src="../_grid/rows.js"></script>
+ <script type="text/javascript" src="../_grid/focus.js"></script>
+ <script type="text/javascript" src="../_grid/selection.js"></script>
+ <script type="text/javascript" src="../_grid/edit.js"></script>
+ <script type="text/javascript" src="../_grid/view.js"></script>
+ <script type="text/javascript" src="../_grid/views.js"></script>
+ <script type="text/javascript" src="../_grid/rowbar.js"></script>
+ <script type="text/javascript" src="../_grid/publicEvents.js"></script>
+ <script type="text/javascript" src="../VirtualGrid.js"></script>
+ <script type="text/javascript" src="../_data/fields.js"></script>
+ <script type="text/javascript" src="../_data/model.js"></script>
+ <script type="text/javascript" src="../_data/editors.js"></script>
+ <script type="text/javascript" src="../Grid.js"></script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ // a grid view is a group of columns
+ var view1 = {
+ cells: [[
+ {name: 'Column 0'}, {name: 'Column 1', width: "10em"}, {name: 'Column 2', width:"100px"}, {name: 'Column 3 is 25%', width: "25%"}, {name: 'Column 4 is 75% of the remaining space', width: "75%"}
+ ]]
+ };
+ // a grid layout is an array of views.
+ var layout = [ view1 ];
+
+
+ var layout2 = [// array of view objects
+ { type: 'dojox.GridRowView', width: '20px' },
+ { noscroll: true, cells: [// array of rows, a row is an array of cells
+ [{ name: "Alpha", value: '<input type="checkbox"></input>', rowSpan: 2, width: 6, styles: 'text-align:center;' }, { name: "Alpha 2", value: "Alpha2" }],
+ [{ name: "Alpha 3", value: "Alpha3" }]
+ ]},
+ { cells: [
+ [{ name: "Beta", value: 'simple'}, { name: "Beta 2", value: "Beta 2" }, { name: "Beta 3", value: "Beta 3" }, { name: "Beta 4", value: "Beta 4", width: "auto" }, { name: "Beta 5 is good", value: "Beta 5", width: "auto" }],
+ [{ name: "Summary", colSpan: 5, value: 'Summary' }]
+ ]},
+ { noscroll: true, cells: [
+ [{ name: "Gamma", value: "Gamma" }, { name: "Gamma2", value: "<button>Radiate</button>", styles: 'text-align:center;' }]]
+ }];
+</script>
+</head>
+<body>
+<div class="heading">dojox.Grid Basic Test</div>
+<div jsid="grid" id="grid" dojoType="dojox.Grid" model="model" structure="layout"></div>
+<br /><br />
+<div jsid="grid2" id="grid2" dojoType="dojox.VirtualGrid" model="model" structure="layout2" rowCount="50"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_grid_layout.html b/includes/js/dojox/grid/tests/test_grid_layout.html
new file mode 100644
index 0000000..148025d
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_grid_layout.html
@@ -0,0 +1,112 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>dojox.Grid in Layout Demo</title>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ @import "../_grid/tundraGrid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/themes/tundra/tundra.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+
+ html, body{
+ width: 100%; /* make the body expand to fill the visible window */
+ height: 100%;
+ padding: 0 0 0 0;
+ margin: 0 0 0 0;
+ overflow: hidden;
+ }
+ .dijitSplitPane{
+ margin: 5px;
+ }
+
+ /* make grid containers overflow hidden */
+ body .dijitContentPane {
+ overflow: hidden;
+ }
+ #rightPane {
+ margin: 0;
+ }
+ </style>
+
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="parseOnLoad: true, isDebug: false"></script>
+ <script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+ <script type="text/javascript">
+ dojo.require("dijit.layout.LayoutContainer");
+ dojo.require("dijit.layout.ContentPane");
+ dojo.require("dijit.layout.LinkPane");
+ dojo.require("dijit.layout.SplitContainer");
+ dojo.require("dijit.layout.TabContainer");
+
+ dojo.require("dojox.grid.Grid");
+
+ dojo.require("dojo.parser"); // scan page for widgets and instantiate them
+ </script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ // a grid view is a group of columns
+ var view1 = {
+ cells: [[
+ {name: 'Column 0'}, {name: 'Column 1'}, {name: 'Column 2'}, {name: 'Column 3', width: "150px"}, {name: 'Column 4'}
+ ],[
+ {name: 'Column 5'}, {name: 'Column 6'}, {name: 'Column 7'}, {name: 'Column 8', field: 3, colSpan: 2}
+ ]]
+ };
+ // a grid layout is an array of views.
+ var layout = [ view1 ];
+ var layout2 = [ {
+ cells: [[
+ {name: 'Alpha'}, {name: 'Beta'}, {name: 'Gamma'}, {name: 'Delta', width: "150px"}, {name: 'Epsilon'}, {name: 'Nexilon'}, {name: 'Zeta'}, {name: 'Eta', field: 0}, {name: 'Omega' }
+ ]]
+ }
+ ];
+ //
+ dojo.addOnLoad(function(){
+ dijit.byId("grid3").update();
+ });
+ </script>
+</head>
+<body class="tundra">
+ <div id="outer" dojoType="dijit.layout.LayoutContainer"
+ style="width: 100%; height: 100%;">
+ <div id="topBar" dojoType="dijit.layout.ContentPane" layoutAlign="top"
+ style="background-color: #274383; color: white;">
+ top bar
+ </div>
+ <div id="bottomBar" dojoType="dijit.layout.ContentPane" layoutAlign="bottom"
+ style="background-color: #274383; color: white;">
+ bottom bar
+ </div>
+ <div id="horizontalSplit" dojoType="dijit.layout.SplitContainer"
+ orientation="horizontal"
+ sizerWidth="5"
+ activeSizing="0"
+ layoutAlign="client"
+ >
+ <div id="leftPane" dojoType="dijit.layout.ContentPane"
+ sizeMin="20" sizeShare="20">
+ Left side
+ </div>
+
+ <div id="rightPane"
+ dojoType="dijit.layout.SplitContainer"
+ orientation="vertical"
+ sizerWidth="5"
+ activeSizing="0"
+ sizeMin="50" sizeShare="80"
+ >
+ <div id="mainTabContainer" dojoType="dijit.layout.TabContainer" sizeMin="20" sizeShare="70">
+ <div id="grid1" dojoType="dojox.Grid" model="model" title="Tab 1"></div>
+ <div id="grid2" dojoType="dojox.Grid" model="model" structure="layout2" title="Tab 2"></div>
+ </div>
+ <div id="bottomRight" dojoType="dijit.layout.ContentPane" sizeMin="20" sizeShare="30">
+ <div id="grid3" dojoType="dojox.Grid" model="model" structure="layout2"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_grid_layout_LayoutContainer.html b/includes/js/dojox/grid/tests/test_grid_layout_LayoutContainer.html
new file mode 100644
index 0000000..4cf12ac
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_grid_layout_LayoutContainer.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>dojox.Grid in Layout Demo</title>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ @import "../_grid/tundraGrid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/themes/tundra/tundra.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+
+ html, body{
+ width: 100%; /* make the body expand to fill the visible window */
+ height: 100%;
+ padding: 0 0 0 0;
+ margin: 0 0 0 0;
+ overflow: hidden;
+ }
+ .dijitSplitPane{
+ margin: 5px;
+ }
+
+ /* make grid containers overflow hidden */
+ body .dijitContentPane {
+ overflow: hidden;
+ }
+ #rightPane {
+ margin: 0;
+ }
+ </style>
+
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="parseOnLoad: true, isDebug: false"></script>
+ <script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+ <script type="text/javascript">
+ dojo.require("dijit.layout.LayoutContainer");
+ dojo.require("dijit.layout.ContentPane");
+ dojo.require("dijit.layout.LinkPane");
+ dojo.require("dijit.layout.SplitContainer");
+ dojo.require("dijit.layout.TabContainer");
+
+ dojo.require("dojox.grid.Grid");
+
+ dojo.require("dojo.parser"); // scan page for widgets and instantiate them
+ </script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ // a grid view is a group of columns
+ var view1 = {
+ cells: [[
+ {name: 'Column 0'}, {name: 'Column 1'}, {name: 'Column 2'}, {name: 'Column 3', width: "150px"}, {name: 'Column 4'}
+ ],[
+ {name: 'Column 5'}, {name: 'Column 6'}, {name: 'Column 7'}, {name: 'Column 8', field: 3, colSpan: 2}
+ ]]
+ };
+ // a grid layout is an array of views.
+ var layout = [ view1 ];
+ var layout2 = [ {
+ cells: [[
+ {name: 'Alpha'}, {name: 'Beta'}, {name: 'Gamma'}, {name: 'Delta', width: "150px"}, {name: 'Epsilon'}, {name: 'Nexilon'}, {name: 'Zeta'}, {name: 'Eta', field: 0}, {name: 'Omega' }
+ ]]
+ }
+ ];
+ //
+ </script>
+</head>
+<body class="tundra">
+ <div id="outer" dojoType="dijit.layout.LayoutContainer"
+ style="width: 100%; height: 100%;">
+
+ <div id="topBar" dojoType="dijit.layout.ContentPane" layoutAlign="top"
+ style="background-color: #274383; color: white; height:100px">
+ top bar
+ </div>
+ <div id="bottomBar" dojoType="dijit.layout.ContentPane" layoutAlign="bottom"
+ style="background-color: #274383; color: white;">
+ bottom bar
+ </div>
+
+ <div id="grid1" dojoType="dojox.Grid" model="model" layoutAlign="client"></div>
+
+
+ </div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_grid_layout_borderContainer.html b/includes/js/dojox/grid/tests/test_grid_layout_borderContainer.html
new file mode 100644
index 0000000..8f0d8d7
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_grid_layout_borderContainer.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Test dojox.Grid Editing</title>
+ <style>
+ @import "../_grid/tundraGrid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/themes/tundra/tundra.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+
+ html, body {
+ width: 100%; /* make the body expand to fill the visible window */
+ height: 100%;
+ overflow: hidden; /* erase window level scrollbars */
+ padding: 0 0 0 0;
+ margin: 0 0 0 0;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug:false, parseOnLoad: true"></script>
+
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dijit.layout.BorderContainer");
+ dojo.require("dijit.layout.ContentPane");
+ dojo.require("dojo.parser");
+ </script>
+
+ <script type="text/javascript">
+ // ==========================================================================
+ // Create a data model
+ // ==========================================================================
+ data = [
+ [ "normal", false, "new", 'But are not followed by two hexadecimal', 29.91, 10, false ],
+ [ "important", false, "new", 'Because a % sign always indicates', 9.33, -5, false ],
+ [ "important", false, "read", 'Signs can be selectively', 19.34, 0, true ],
+ [ "note", false, "read", 'However the reserved characters', 15.63, 0, true ],
+ [ "normal", false, "replied", 'It is therefore necessary', 24.22, 5.50, true ],
+ [ "important", false, "replied", 'To problems of corruption by', 9.12, -3, true ],
+ [ "note", false, "replied", 'Which would simply be awkward in', 12.15, -4, false ]
+ ];
+ var rows = 10000;
+ for(var i=0, l=data.length; i<rows-l; i++){
+ data.push(data[i%l].slice(0));
+ }
+ model = new dojox.grid.data.Table(null, data);
+
+ // ==========================================================================
+ // Grid structure
+ // ==========================================================================
+ gridLayout = [
+ {
+ type: 'dojox.GridRowView', width: '20px'
+ },
+ {
+ defaultCell: { width: 8, editor: dojox.grid.editors.Input, styles: 'text-align: right;' },
+ rows: [
+ [
+ { name: 'Id', width: 3, get: function(inRowIndex){ return inRowIndex+1;} },
+ { name: 'Priority', styles: 'text-align: center;', editor: dojox.grid.editors.Select, options: ["normal", "note", "important"]},
+ { name: 'Mark', width: 3, styles: 'text-align: center;', editor: dojox.grid.editors.Bool },
+ { name: 'Status', field: 2, styles: 'text-align: center;', editor: dojox.grid.editors.Select, options: [ "new", "read", "replied" ]},
+ { name: 'Message', styles: '', width: '100%' },
+ { name: 'Amount'}
+ ]
+ ]
+ }
+ ];
+ </script>
+ </head>
+ <body class="tundra">
+<div dojoType="dijit.layout.BorderContainer" liveSplitters="false" persist="true"
+ id="verticalSplitParam" design="headline" style="width: 100%; height: 100%;">
+
+ <div dojoType="dijit.layout.ContentPane" id="mybuttons" region="top"
+ splitter="true" style="width: 100%; height: 10%;">
+
+ <div id="controls">
+ <button onclick="grid.refresh()">Refresh</button>
+ <button onclick="grid.edit.focusEditor()">Focus Editor</button>
+ <button onclick="grid.focus.next()">Next Focus</button>
+ <button onclick="addRow()">Add Row</button>
+ <button onclick="grid.removeSelectedRows()">Remove</button>
+ <button onclick="grid.edit.apply()">Apply</button>
+ <button onclick="grid.edit.cancel()">Cancel</button>
+ <button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button>
+ </div>
+ </div>
+
+ <div dojoType="dijit.layout.ContentPane" id="gridContainer1" region="center" splitter="true" style="background: red;" >
+ <div jsId="grid" class="myGrid" dojoType="dojox.Grid" model="model" structure="gridLayout"></div>
+ </div>
+
+</div>
+
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_grid_object_model_change.html b/includes/js/dojox/grid/tests/test_grid_object_model_change.html
new file mode 100644
index 0000000..54c6808
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_grid_object_model_change.html
@@ -0,0 +1,86 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>Test dojox.grid.data.Objects model change</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ width: 35em;
+ height: 30em;
+ }
+ #grid2 {
+ border: 1px solid #333;
+ width: 35em;
+ height: 30em;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+ <!--<script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>-->
+ <!-- Debugging -->
+ <script type="text/javascript" src="../_grid/lib.js"></script>
+ <script type="text/javascript" src="../_grid/drag.js"></script>
+ <script type="text/javascript" src="../_grid/scroller.js"></script>
+ <script type="text/javascript" src="../_grid/builder.js"></script>
+ <script type="text/javascript" src="../_grid/cell.js"></script>
+ <script type="text/javascript" src="../_grid/layout.js"></script>
+ <script type="text/javascript" src="../_grid/rows.js"></script>
+ <script type="text/javascript" src="../_grid/focus.js"></script>
+ <script type="text/javascript" src="../_grid/selection.js"></script>
+ <script type="text/javascript" src="../_grid/edit.js"></script>
+ <script type="text/javascript" src="../_grid/view.js"></script>
+ <script type="text/javascript" src="../_grid/views.js"></script>
+ <script type="text/javascript" src="../_grid/rowbar.js"></script>
+ <script type="text/javascript" src="../_grid/publicEvents.js"></script>
+ <script type="text/javascript" src="../VirtualGrid.js"></script>
+ <script type="text/javascript" src="../_data/fields.js"></script>
+ <script type="text/javascript" src="../_data/model.js"></script>
+ <script type="text/javascript" src="../_data/editors.js"></script>
+ <script type="text/javascript" src="../Grid.js"></script>
+ <script type="text/javascript" src="support/test_data_objects.js"></script>
+ <script type="text/javascript">
+ // a grid view is a group of columns
+ var view1 = {
+ cells: [[
+ {name: 'Column 0', field: 'col1'},
+ {name: 'Column 1', field: 'col2'},
+ {name: 'Column 2', field: 'col3'},
+ {name: 'Column 3', field: 'col4', width: "150px"},
+ {name: 'Column 4', field: 'col5'}
+ ],[
+ {name: 'Column 5', field: 'col6'},
+ {name: 'Column 6', field: 'col7'},
+ {name: 'Column 7'},
+ {name: 'Column 8', field: 'col4', colSpan: 2}
+ ]]
+ };
+ // a grid layout is an array of views.
+ var layout = [ view1 ];
+
+ dojo.addOnLoad(function(){
+ model.setData(data);
+
+ var newModel = new dojox.grid.data.Objects(null, data);
+ dijit.byId("grid2").setModel(newModel);
+ });
+</script>
+</head>
+<body>
+<div class="heading">dojox.grid.data.Objects model change</div>
+<div id="grid" dojoType="dojox.Grid" model="model" structure="layout"></div>
+<div id="grid2" dojoType="dojox.Grid" model="model2" structure="layout"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_grid_programmatic.html b/includes/js/dojox/grid/tests/test_grid_programmatic.html
new file mode 100644
index 0000000..fe0794f
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_grid_programmatic.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <title>Test dojox.Grid Programmatic Instantiation</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../../../dojo/resources/dojo.css";
+ @import "../_grid/tundraGrid.css";
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ width: 50em;
+ height: 30em;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug:false, debugAtAllCosts: false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ dojo.addOnLoad(function(){
+ // a grid view is a group of columns
+ var view1 = {
+ cells: [
+ [
+ {name: 'Column 0'},
+ {name: 'Column 1'},
+ {name: 'Column 2'},
+ {name: 'Column 3', width: "150px"},
+ {name: 'Column 4'}
+ ],
+ [
+ {name: 'Column 5'},
+ {name: 'Column 6'},
+ {name: 'Column 7'},
+ {name: 'Column 8', field: 3, colSpan: 2}
+ ]
+ ]
+ };
+ // a grid layout is an array of views.
+ var layout = [ view1 ];
+
+ var grid = new dojox.Grid({
+ "id": "grid",
+ "model": model,
+ "structure": layout
+ });
+ dojo.byId("gridContainer").appendChild(grid.domNode);
+ grid.render();
+ });
+ </script>
+ </head>
+ <body class="tundra">
+ <div class="heading">dojox.Grid Programmatic Instantiation Test</div>
+ <div id="gridContainer"></div>
+ </body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_grid_programmatic_layout.html b/includes/js/dojox/grid/tests/test_grid_programmatic_layout.html
new file mode 100644
index 0000000..b55d975
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_grid_programmatic_layout.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <title>Test dojox.Grid Programmatic Instantiation</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/tundraGrid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/themes/tundra/tundra.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #grid {
+ width: 100%;
+ height: 100%;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug:false, debugAtAllCosts: false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dijit.layout.TabContainer");
+ dojo.require("dijit.layout.ContentPane");
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ dojo.addOnLoad(function(){
+ // a grid view is a group of columns
+ var view1 = {
+ cells: [
+ [
+ {name: 'Column 0'},
+ {name: 'Column 1'},
+ {name: 'Column 2'},
+ {name: 'Column 3', width: "150px"},
+ {name: 'Column 4'}
+ ],
+ [
+ {name: 'Column 5'},
+ {name: 'Column 6'},
+ {name: 'Column 7'},
+ {name: 'Column 8', field: 3, colSpan: 2}
+ ]
+ ]
+ };
+ // a grid layout is an array of views.
+ var layout = [ view1 ];
+
+ var grid = new dojox.Grid({
+ title: "tab 1",
+ id: "grid",
+ model: model,
+ structure: layout
+ });
+ dijit.byId("mainTabContainer").addChild(grid, 0);
+ grid.render();
+ });
+ </script>
+ </head>
+ <body class="tundra">
+ <div class="heading">dojox.Grid Programmatic Instantiation Test</div>
+ <div id="mainTabContainer" dojoType="dijit.layout.TabContainer"
+ style="height: 300px; width: 100%;">
+ <div dojoType="dijit.layout.ContentPane" title="Tab 2">
+ ... stuff ...
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_grid_rtl.html b/includes/js/dojox/grid/tests/test_grid_rtl.html
new file mode 100644
index 0000000..c1b253d
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_grid_rtl.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>Test dojox.Grid Basic</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ @import "../_grid/Grid_rtl.css";
+ @import "../_grid/tundraGrid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/themes/tundra/tundra.css";
+ @import "../../../dijit/themes/tundra/tundra_rtl.css";
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ width: 35em;
+ height: 30em;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+ <!--<script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>-->
+ <!-- Debugging -->
+ <script type="text/javascript" src="../_grid/lib.js"></script>
+ <script type="text/javascript" src="../_grid/drag.js"></script>
+ <script type="text/javascript" src="../_grid/scroller.js"></script>
+ <script type="text/javascript" src="../_grid/builder.js"></script>
+ <script type="text/javascript" src="../_grid/cell.js"></script>
+ <script type="text/javascript" src="../_grid/layout.js"></script>
+ <script type="text/javascript" src="../_grid/rows.js"></script>
+ <script type="text/javascript" src="../_grid/focus.js"></script>
+ <script type="text/javascript" src="../_grid/selection.js"></script>
+ <script type="text/javascript" src="../_grid/edit.js"></script>
+ <script type="text/javascript" src="../_grid/view.js"></script>
+ <script type="text/javascript" src="../_grid/views.js"></script>
+ <script type="text/javascript" src="../_grid/rowbar.js"></script>
+ <script type="text/javascript" src="../_grid/publicEvents.js"></script>
+ <script type="text/javascript" src="../VirtualGrid.js"></script>
+ <script type="text/javascript" src="../_data/fields.js"></script>
+ <script type="text/javascript" src="../_data/model.js"></script>
+ <script type="text/javascript" src="../_data/editors.js"></script>
+ <script type="text/javascript" src="../Grid.js"></script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ // a grid view is a group of columns
+ var view1 = {
+ cells: [[
+ {name: 'Column 0'}, {name: 'Column 1'}, {name: 'Column 2'}, {name: 'Column 3', width: "150px"}, {name: 'Column 4'}
+ ],[
+ {name: 'Column 5'}, {name: 'Column 6'}, {name: 'Column 7'}, {name: 'Column 8', field: 3, colSpan: 2}
+ ]]
+ };
+ // a grid layout is an array of views.
+ var layout = [ view1 ];
+</script>
+</head>
+<body dir="rtl">
+<div class="heading">dojox.Grid Basic Test</div>
+<div id="grid" dojoType="dojox.Grid" model="model" structure="layout"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_grid_themes.html b/includes/js/dojox/grid/tests/test_grid_themes.html
new file mode 100644
index 0000000..e0f80f6
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_grid_themes.html
@@ -0,0 +1,118 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid themes</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../../../dojo/resources/dojo.css";
+ @import "../_grid/tundraGrid.css";
+ @import "../_grid/soriaGrid.css";
+ @import "../_grid/nihiloGrid.css";
+
+ #grid, #grid2 {
+ width: 65em;
+ height: 25em;
+ padding: 1px;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.data.ItemFileReadStore");
+ dojo.require("dojox.data.CsvStore");
+ dojo.require("dojo.parser");
+ </script>
+
+</head>
+<body>
+ <h5>dojox.grid.Grid structure from markup (tundra theme)</h5>
+ <span dojoType="dojox.data.CsvStore"
+ jsId="csvStore" url="support/movies.csv">
+ </span>
+
+ <table class="tundra" dojoType="dojox.grid.Grid"
+ store="csvStore"
+ query="{ Title: '*' }"
+ clientSort="true"
+ style="width: 800px; height: 300px;">
+ <thead>
+ <tr>
+ <th width="300px" field="Title">Title of Movie</th>
+
+ <th width="5em">Year</th>
+ </tr>
+ <tr>
+ <th colspan="2">Producer</th>
+ </tr>
+ </thead>
+ </table>
+
+ <span dojoType="dojo.data.ItemFileReadStore"
+ jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+ </span>
+ <h5>Locked views specified with tables and colgroups (soria theme)</h5>
+
+ <table class="soria" dojoType="dojox.grid.Grid"
+ store="jsonStore"
+ rowsPerPage="20"
+ query="{ name: '*' }"
+ style="width: 600px; height: 300px;">
+ <colgroup span="1" noscroll="true" width="300px"></colgroup>
+ <colgroup span="4"></colgroup>
+ <thead>
+
+ <tr>
+ <th field="name">Country/Continent Name</th>
+ <th width="100px" field="population">Population</th>
+ <th width="100px" field="area">Land Mass</th>
+ <th width="100px" field="timezone">Time Zone</th>
+ <th width="5em" field="type">Type</th>
+
+ </tr>
+ </thead>
+ </table>
+
+ <h5>A "regular" Grid from markup (no table defintion, nihilo theme)</h5>
+ <script type="text/javascript">
+ // helper functions and structure definitions for the old markup construction syntax
+ function getRow(inRowIndex){
+ return ' ' + inRowIndex;
+ }
+
+ var layoutCountries = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ {
+ cells: [
+ [
+ { name: "Row", get: getRow, width: 5}
+ ]
+ ],
+ noscroll: true
+ },
+ // view 2
+ {
+ cells: [
+ [
+ { field: 0, width: 'auto' },
+ { width: 8 }
+ ]
+ ]
+ }
+ ];
+ </script>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel2"
+ rowsPerPage="20"
+ store="jsonStore"
+ query="{ name : '*' }">
+ </span>
+
+ <div class="nihilo" id="grid2" dojoType="dojox.grid.Grid" elasticView="2"
+ model="dataModel2" structure="layoutCountries">
+ </div>
+
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_grid_tooltip_menu.html b/includes/js/dojox/grid/tests/test_grid_tooltip_menu.html
new file mode 100644
index 0000000..52c7726
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_grid_tooltip_menu.html
@@ -0,0 +1,161 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>Test dojox.Grid Basic</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ width: 35em;
+ height: 30em;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+ <script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dijit.Tooltip");
+ dojo.require("dijit.Menu");
+ dojo.require("dijit.ColorPalette");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ // a grid view is a group of columns
+ var view1 = {
+ cells: [[
+ {name: 'Column 0'}, {name: 'Column 1'}, {name: 'Column 2'}, {name: 'Column 3', width: "150px"}, {name: 'Column 4'}
+ ],[
+ {name: 'Column 5'}, {name: 'Column 6'}, {name: 'Column 7'}, {name: 'Column 8', field: 3, colSpan: 2}
+ ]]
+ };
+ // a grid layout is an array of views.
+ var layout = [ view1 ];
+
+ dojo.addOnLoad(function() {
+ window["grid"] = dijit.byId("grid");
+ var
+ showTooltip = function(e) {
+ if(gridTooltipEnabled){
+ var msg = "This is cell " + e.rowIndex + ", " + e.cellIndex;
+ dijit.showTooltip(msg, e.cellNode);
+ }
+ },
+ hideTooltip = function(e) {
+ dijit.hideTooltip(e.cellNode);
+ // FIXME: make sure that pesky tooltip doesn't reappear!
+ // would be nice if there were a way to hide tooltip without regard to aroundNode.
+ dijit._masterTT._onDeck=null;
+ }
+
+ // cell tooltip
+ dojo.connect(grid, "onCellMouseOver", showTooltip);
+ dojo.connect(grid, "onCellMouseOut", hideTooltip);
+ // header cell tooltip
+ dojo.connect(grid, "onHeaderCellMouseOver", showTooltip);
+ dojo.connect(grid, "onHeaderCellMouseOut", hideTooltip);
+
+ // grid menu
+ window["gridMenu"] = dijit.byId("gridMenu");
+ gridMenu.bindDomNode(grid.domNode);
+ // prevent grid methods from killing the context menu event by implementing our own handler
+ grid.onCellContextMenu = function(e) {
+ cellNode = e.cellNode;
+ };
+ grid.onHeaderContextMenu = function(e) {
+ cellNode = e.cellNode;
+ };
+ });
+
+ function reportCell() {
+ if(cellNode){
+ alert("Cell contents: " + cellNode.innerHTML);
+ cellNode = null;
+ }
+ }
+
+ gridTooltipEnabled = true;
+ function toggleTooltip(button){
+ gridTooltipEnabled = !gridTooltipEnabled;
+ button.value = gridTooltipEnabled ? "Disable Grid Tooltip" : "Enable Grid Tooltip";
+ }
+
+ gridMenuEnabled = true;
+ function toggleMenu(button){
+ gridMenuEnabled = !gridMenuEnabled;
+ button.value = gridMenuEnabled ? "Disable Grid Menu" : "Enable Grid Menu";
+ gridMenu[gridMenuEnabled ? "bindDomNode" : "unBindDomNode"](grid.domNode);
+ }
+</script>
+</head>
+<body>
+<div dojoType="dijit.Menu" id="gridMenu" style="display: none;">
+ <div dojoType="dijit.MenuItem" onClick="reportCell">See cell text...</div>
+ <div dojoType="dijit.MenuItem" disabled="true">Disabled Item</div>
+ <div dojoType="dijit.MenuSeparator"></div>
+ <div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut"
+ onClick="alert('not actually cutting anything, just a test!')">Cut</div>
+ <div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy"
+ onClick="alert('not actually copying anything, just a test!')">Copy</div>
+ <div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+ onClick="alert('not actually pasting anything, just a test!')">Paste</div>
+ <div dojoType="dijit.MenuSeparator"></div>
+</div>
+<div dojoType="dijit.Menu" id="submenu1" contextMenuForWindow="true" style="display: none;">
+ <div dojoType="dijit.MenuItem" onClick="alert('Hello world');">Enabled Item</div>
+ <div dojoType="dijit.MenuItem" disabled="true">Disabled Item</div>
+ <div dojoType="dijit.MenuSeparator"></div>
+ <div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut"
+ onClick="alert('not actually cutting anything, just a test!')">Cut</div>
+ <div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy"
+ onClick="alert('not actually copying anything, just a test!')">Copy</div>
+ <div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+ onClick="alert('not actually pasting anything, just a test!')">Paste</div>
+ <div dojoType="dijit.MenuSeparator"></div>
+ <div dojoType="dijit.PopupMenuItem">
+ <span>Enabled Submenu</span>
+ <div dojoType="dijit.Menu" id="submenu2">
+ <div dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</div>
+ <div dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</div>
+ <div dojoType="dijit.PopupMenuItem">
+ <span>Deeper Submenu</span>
+ <div dojoType="dijit.Menu" id="submenu4"">
+ <div dojoType="dijit.MenuItem" onClick="alert('Sub-submenu 1!')">Sub-sub-menu Item One</div>
+ <div dojoType="dijit.MenuItem" onClick="alert('Sub-submenu 2!')">Sub-sub-menu Item Two</div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div dojoType="dijit.PopupMenuItem" disabled="true">
+ <span>Disabled Submenu</span>
+ <div dojoType="dijit.Menu" id="submenu3" style="display: none;">
+ <div dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</div>
+ <div dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</div>
+ </div>
+ </div>
+ <div dojoType="dijit.PopupMenuItem">
+ <span>Different popup</span>
+ <div dojoType="dijit.ColorPalette"></div>
+ </div>
+</div>
+<div class="heading">dojox.Grid Basic Test</div>
+<p>
+ <input type="button" onclick="toggleTooltip(this)" value="Disable Grid Tooltip">&nbsp;&nbsp;
+ <input type="button" onclick="toggleMenu(this)" value="Disable Grid Menu">&nbsp;&nbsp;<br />
+ Note: when the grid menu is disabled, the document's dijit context menu should be shown over the grid.
+</p>
+<div id="grid" dojoType="dojox.Grid" model="model" structure="layout"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_keyboard.html b/includes/js/dojox/grid/tests/test_keyboard.html
new file mode 100644
index 0000000..69d4046
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_keyboard.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>Test dojox.Grid Basic</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ width: 35em;
+ height: 30em;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+ <!--<script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>-->
+ <!-- Debugging -->
+ <script type="text/javascript" src="../_grid/lib.js"></script>
+ <script type="text/javascript" src="../_grid/drag.js"></script>
+ <script type="text/javascript" src="../_grid/scroller.js"></script>
+ <script type="text/javascript" src="../_grid/builder.js"></script>
+ <script type="text/javascript" src="../_grid/cell.js"></script>
+ <script type="text/javascript" src="../_grid/layout.js"></script>
+ <script type="text/javascript" src="../_grid/rows.js"></script>
+ <script type="text/javascript" src="../_grid/focus.js"></script>
+ <script type="text/javascript" src="../_grid/selection.js"></script>
+ <script type="text/javascript" src="../_grid/edit.js"></script>
+ <script type="text/javascript" src="../_grid/view.js"></script>
+ <script type="text/javascript" src="../_grid/views.js"></script>
+ <script type="text/javascript" src="../_grid/rowbar.js"></script>
+ <script type="text/javascript" src="../_grid/publicEvents.js"></script>
+ <script type="text/javascript" src="../VirtualGrid.js"></script>
+ <script type="text/javascript" src="../_data/fields.js"></script>
+ <script type="text/javascript" src="../_data/model.js"></script>
+ <script type="text/javascript" src="../_data/editors.js"></script>
+ <script type="text/javascript" src="../Grid.js"></script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ // a grid view is a group of columns
+ var view1 = {
+ cells: [[
+ {name: 'Column 0'}, {name: 'Column 1'}, {name: 'Column 2'}, {name: 'Column 3', width: "150px"}, {name: 'Column 4'},
+ {name: 'Column 5'}, {name: 'Column 6'}, {name: 'Column 7', field: 0}, {name: 'Column 8'},
+ {name: 'Column 9'}, {name: 'Column 10'}, {name: 'Column 11', field: 0}, {name: 'Column 12', width: "150px"}, {name: 'Column 13'},
+ {name: 'Column 14'}, {name: 'Column 15'}, {name: 'Column 16', field: 0}, {name: 'Column 17'}
+ ]]
+ };
+ // a grid layout is an array of views.
+ var layout = [ view1 ];
+
+
+ function keyDown(e) {
+ switch(e.keyCode){
+ case dojo.keys.LEFT_ARROW:
+ console.log('left arrow!');
+ break;
+ case dojo.keys.RIGHT_ARROW:
+ console.log('right arrow!');
+ break;
+ case dojo.keys.ENTER:
+ console.log('enter!');
+ break;
+ }
+
+
+ }
+
+ dojo.addOnLoad(function() {
+ window["grid"] = dijit.byId("grid");
+ dojo.connect(grid, "onKeyDown", keyDown);
+ });
+
+</script>
+</head>
+<body>
+<div class="heading">dojox.Grid Basic Test</div>
+<div id="grid" dojoType="dojox.Grid" model="model" structure="layout"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_markup.html b/includes/js/dojox/grid/tests/test_markup.html
new file mode 100644
index 0000000..7c57710
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_markup.html
@@ -0,0 +1,112 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid with Dojo.Data via binding</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../../../dojo/resources/dojo.css";
+ @import "../_grid/tundraGrid.css";
+
+ #grid, #grid2 {
+ width: 65em;
+ height: 25em;
+ padding: 1px;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.data.ItemFileReadStore");
+ dojo.require("dojox.data.CsvStore");
+ dojo.require("dojo.parser");
+ </script>
+</head>
+<body class="tundra">
+ <h5>dojox.grid.Grid structure from markup</h5>
+ <span dojoType="dojox.data.CsvStore"
+ jsId="csvStore" url="support/movies.csv">
+ </span>
+
+ <table dojoType="dojox.grid.Grid"
+ store="csvStore"
+ query="{ Title: '*' }"
+ clientSort="true"
+ style="width: 800px; height: 300px;">
+ <thead>
+ <tr>
+ <th width="300px" field="Title">Title of Movie</th>
+ <th width="5em">Year</th>
+ </tr>
+ <tr>
+ <th colspan="2">Producer</th>
+ </tr>
+ </thead>
+ </table>
+
+
+ <span dojoType="dojo.data.ItemFileReadStore"
+ jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+ </span>
+ <h5>Locked views specified with tables and colgroups</h5>
+
+ <table dojoType="dojox.grid.Grid"
+ store="jsonStore"
+ rowsPerPage="20"
+ query="{ name: '*' }"
+ style="width: 600px; height: 300px;">
+ <colgroup span="1" noscroll="true" width="300px"></colgroup>
+ <colgroup span="4"></colgroup>
+ <thead>
+ <tr>
+ <th field="name">Country/Continent Name</th>
+ <th width="100px" field="population">Population</th>
+ <th width="100px" field="area">Land Mass</th>
+ <th width="100px" field="timezone">Time Zone</th>
+ <th width="5em" field="type">Type</th>
+ </tr>
+ </thead>
+ </table>
+
+ <h5>A "regular" Grid from markup (no table defintion)</h5>
+ <script type="text/javascript">
+ // helper functions and structure definitions for the old markup construction syntax
+ function getRow(inRowIndex){
+ return ' ' + inRowIndex;
+ }
+
+ var layoutCountries = [
+ // view 0
+ { type: 'dojox.GridRowView', width: '20px' },
+ // view 1
+ {
+ cells: [
+ [
+ { name: "Row", get: getRow, width: 5}
+ ]
+ ],
+ noscroll: true
+ },
+ // view 2
+ {
+ cells: [
+ [
+ { field: 0, width: 'auto' },
+ { width: 8 }
+ ]
+ ]
+ }
+ ];
+ </script>
+ <span dojoType="dojox.grid.data.DojoData"
+ jsId="dataModel2"
+ rowsPerPage="20"
+ store="jsonStore"
+ query="{ name : '*' }">
+ </span>
+ <div id="grid2" dojoType="dojox.grid.Grid" elasticView="2"
+ model="dataModel2" structure="layoutCountries">
+ </div>
+
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_mysql_edit.html b/includes/js/dojox/grid/tests/test_mysql_edit.html
new file mode 100644
index 0000000..dd6a762
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_mysql_edit.html
@@ -0,0 +1,155 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html debug="true">
+<head>
+ <title>dojox.Grid Test: Mysql Table Editing</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style>
+ @import "../_grid/tundraGrid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/themes/tundra/tundra.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+
+ .grid {
+ height: 30em;
+ }
+ </style>
+
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+ <script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+ <!--<script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojox.grid.tests.databaseModel");
+ dojo.require("dojo.parser");
+ </script>-->
+ <!-- Debugging -->
+ <script type="text/javascript" src="../_grid/lib.js"></script>
+ <script type="text/javascript" src="../_grid/drag.js"></script>
+ <script type="text/javascript" src="../_grid/scroller.js"></script>
+ <script type="text/javascript" src="../_grid/builder.js"></script>
+ <script type="text/javascript" src="../_grid/cell.js"></script>
+ <script type="text/javascript" src="../_grid/layout.js"></script>
+ <script type="text/javascript" src="../_grid/rows.js"></script>
+ <script type="text/javascript" src="../_grid/focus.js"></script>
+ <script type="text/javascript" src="../_grid/selection.js"></script>
+ <script type="text/javascript" src="../_grid/edit.js"></script>
+ <script type="text/javascript" src="../_grid/view.js"></script>
+ <script type="text/javascript" src="../_grid/views.js"></script>
+ <script type="text/javascript" src="../_grid/rowbar.js"></script>
+ <script type="text/javascript" src="../_grid/publicEvents.js"></script>
+ <script type="text/javascript" src="../VirtualGrid.js"></script>
+ <script type="text/javascript" src="../_data/fields.js"></script>
+ <script type="text/javascript" src="../_data/model.js"></script>
+ <script type="text/javascript" src="../_data/editors.js"></script>
+ <script type="text/javascript" src="../_data/dijitEditors.js"></script>
+ <script type="text/javascript" src="../Grid.js"></script>
+ <script type="text/javascript" src="databaseModel.js"></script>
+ <script type="text/javascript">
+ var model = new dojox.grid.data.DbTable(null, null, 'support/data.php', "test", "testtbl");
+ // simple display of row info; based on model observing.
+ modelChange = function() {
+ dojo.byId('rowCount').innerHTML = model.count + ' row(s)';
+ }
+ model.observer(this);
+
+ // yay, let's deal with MySql date types, at least a little bit...
+ // NOTE: supports only default date formatting YYYY-MM-DD HH:MM:SS or YY-MM-DD HH:MM:SS
+ mysqlDateToJsDate = function(inMysqlDateTime, inDateDelim, inTimeDelim) {
+ var dt = inMysqlDateTime.split(' '), d = dt[0], t = dt[1], r;
+ d = d&&d.split(inDateDelim||'-');
+ t = t&&t.split(inTimeDelim||':');
+ if (d && d.length == 3) {
+ r = new Date();
+ r.setYear(d[0]);
+ r.setMonth(parseInt(d[1])-1);
+ r.setDate(d[2]);
+ }
+ if (t && t.length == 3) {
+ r = r || new Date();
+ r.setHours(t[0]);
+ r.setMinutes(t[1]);
+ r.setSeconds(t[2]);
+ }
+ return r || new Date(inMysqlDateTime);
+ }
+
+ jsDateToMySqlDate = function(inDate) {
+ var
+ d = new Date(inDate),
+ y = d.getFullYear(),
+ m = dojo.string.pad(d.getMonth() + 1),
+ dd = dojo.string.pad(d.getDate())
+ return dojo.string.substitute("${0}-${1}-${2}",[y, m, dd]);
+ };
+
+ // custom simple MySql date formatter
+ formatMySqlDate = function(inDatum) {
+ return inDatum != dojox.grid.na ? dojo.date.locale.format(mysqlDateToJsDate(inDatum), this.constraint) : dojox.grid.na;
+ }
+
+ // custom simple MySql date editor
+ dojo.declare("mySqlDateEditor", dojox.grid.editors.DateTextBox, {
+ format: function(inDatum, inRowIndex){
+ inDatum = mysqlDateToJsDate(inDatum);
+ return this.inherited(arguments, [inDatum, inRowIndex]);
+ },
+ getValue: function(inRowIndex){
+ var v = this.editor.getValue(), fv = jsDateToMySqlDate(v);
+ return fv;
+ }
+ });
+
+ var gridLayout = [
+ { type: "dojox.GridRowView", width: "20px" },
+ {
+ defaultCell: { width: 6, editor: dojox.grid.editors.Dijit },
+ cells: [[
+ { name: 'Id', styles: 'text-align: right;', editorClass: "dijit.form.NumberTextBox" },
+ { name: 'Name', width: 20},
+ { name: 'Message', styles: 'text-align: right;'},
+ { name: 'Date',
+ editor: mySqlDateEditor,
+ formatter: formatMySqlDate,
+ constraint: {selector: "date"},
+ width: 10,
+ styles: 'text-align:right;'}
+ ]]}
+ ];
+
+ function waitMessage() {
+ alert('Edit in progress, please wait.');
+ }
+
+ function getDefaultRow() {
+ return ['', '', '', jsDateToMySqlDate(new Date())];
+ }
+ function addRow() {
+ if(model.canModify()){
+ grid.addRow(getDefaultRow());
+ }else{
+ waitMessage();
+ }
+ }
+
+ function removeSelected(){
+ if(model.canModify()){
+ grid.removeSelectedRows();
+ }else{
+ waitMessage();
+ }
+ }
+ </script>
+</head>
+<body class="tundra">
+ <h1>dojox.Grid Test: Mysql Table Editing</h1>
+ <br>
+ <button onclick="addRow()">Add Row</button>&nbsp;&nbsp;
+ <button onclick="removeSelected()">Remove Selected</button>&nbsp;&nbsp;
+ <button onclick="grid.edit.apply()">Apply Edit</button>&nbsp;&nbsp;
+ <button onclick="grid.edit.cancel()">Cancel Edit</button>&nbsp;&nbsp;
+ <button onclick="grid.refresh()">Refresh</button>
+ <br><br>
+ <div jsId="grid" class="grid" structure="gridLayout" dojoType="dojox.Grid" model="model" singleClickEdit="true" autoWidth="true"></div>
+ <div id="rowCount"></div>
+ <p>Note: This test requires MySql and PHP and works with the database table available in support/testtbl.sql.</p>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_sizing.html b/includes/js/dojox/grid/tests/test_sizing.html
new file mode 100644
index 0000000..fdd0897
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_sizing.html
@@ -0,0 +1,175 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid Sizing Example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../../../dojo/resources/dojo.css";
+ @import "../_grid/tundraGrid.css";
+
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #container {
+ width: 400px;
+ height: 200px;
+ border: 4px double #333;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>
+ <!-- Debugging -->
+ <script type="text/javascript" src="../_grid/lib.js"></script>
+ <script type="text/javascript" src="../_grid/drag.js"></script>
+ <script type="text/javascript" src="../_grid/scroller.js"></script>
+ <script type="text/javascript" src="../_grid/builder.js"></script>
+ <script type="text/javascript" src="../_grid/cell.js"></script>
+ <script type="text/javascript" src="../_grid/layout.js"></script>
+ <script type="text/javascript" src="../_grid/rows.js"></script>
+ <script type="text/javascript" src="../_grid/focus.js"></script>
+ <script type="text/javascript" src="../_grid/selection.js"></script>
+ <script type="text/javascript" src="../_grid/edit.js"></script>
+ <script type="text/javascript" src="../_grid/view.js"></script>
+ <script type="text/javascript" src="../_grid/views.js"></script>
+ <script type="text/javascript" src="../_grid/rowbar.js"></script>
+ <script type="text/javascript" src="../_grid/publicEvents.js"></script>
+ <script type="text/javascript" src="../VirtualGrid.js"></script>
+ <script type="text/javascript" src="../_data/fields.js"></script>
+ <script type="text/javascript" src="../_data/model.js"></script>
+ <script type="text/javascript" src="../_data/editors.js"></script>
+ <script type="text/javascript" src="../Grid.js"></script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ data = [
+ [ "normal", false, "new", 'But are not followed by two hexadecimal', 29.91, 10, false ],
+ [ "important", false, "new", 'Because a % sign always indicates', 9.33, -5, false ],
+ [ "important", false, "read", 'Signs can be selectively', 19.34, 0, true ],
+ [ "note", false, "read", 'However the reserved characters', 15.63, 0, true ],
+ [ "normal", false, "replied", 'It is therefore necessary', 24.22, 5.50, true ],
+ [ "important", false, "replied", 'To problems of corruption by', 9.12, -3, true ],
+ [ "note", false, "replied", 'Which would simply be awkward in', 12.15, -4, false ]
+ ];
+ model = new dojox.grid.data.table(null, data);
+
+ // grid structure
+ // a grid view is a group of columns
+ // a special view providing selection feedback
+ var rowBar = {type: 'dojox.GridRowView', width: '20px'};
+
+ // a view without scrollbars
+ var leftView = {
+ noscroll: true,
+ cells: [[
+ {name: 'Column 0'},
+ {name: 'Column 1'}
+ ]]};
+
+ var middleView = {
+ cells: [[
+ {name: 'Column 2'},
+ {name: 'Column 3'},
+ {name: 'Column 4'},
+ {name: 'Column 5'},
+ {name: 'Column 6'},
+ ]]};
+
+ // a grid structure is an array of views.
+ var structure = [ rowBar, leftView, middleView];
+
+ // get can return data for each cell of the grid
+ function get(inRowIndex) {
+ return [this.index, inRowIndex].join(', ');
+ }
+
+ function resizeInfo() {
+ setTimeout(function() {
+ dojo.byId('gridWidth').value = grid.domNode.clientWidth;
+ dojo.byId('gridHeight').value = grid.domNode.clientHeight;
+ }, 1);
+ }
+
+ function resizeGrid() {
+ grid.autoHeight = false;
+ grid.autoWidth = false;
+ var
+ w = Number(dojo.byId('gridWidth').value),
+ h = Number(dojo.byId('gridHeight').value);
+
+ dojo.contentBox(grid.domNode, {w: w, h: h});
+ grid.update();
+ }
+
+ function fitWidth() {
+ grid.autoWidth = true;
+ grid.autoHeight = false;
+ grid.update();
+ }
+
+ function fitHeight() {
+ grid.autoWidth = false;
+ grid.autoHeight = true;
+ grid.update();
+ }
+
+ function fitBoth() {
+ grid.autoWidth = true;
+ grid.autoHeight = true;
+ grid.update();
+ }
+
+ function sizeDefault() {
+ grid.autoWidth = false;
+ grid.autoHeight = false;
+ grid.domNode.style.width = '';
+ grid.domNode.style.height = 0;
+ grid.update();
+ }
+
+ dojo.addOnLoad(function() {
+ window["grid"] = dijit.byId("grid");
+ dojo.byId('gridWidth').value = 500;
+ dojo.byId('gridHeight').value = 200;
+ dojo.connect(grid, 'update', resizeInfo);
+ resizeGrid();
+ window["grid1"] = dijit.byId("grid1");
+ });
+
+
+</script>
+</head>
+<body class="tundra">
+<div class="heading">dojox.Grid Sizing Test</div>
+ Grid width: <input id="gridWidth" type="text">&nbsp;
+ and height: <input id="gridHeight" type="text">&nbsp;
+ <button onclick="resizeGrid()">Resize Grid</button><br><br>
+ <button onclick="fitWidth()">Fit Data Width</button>&nbsp;
+ <button onclick="fitHeight()">Fit Data Height</button>&nbsp;
+ <button onclick="fitBoth()">Fit Data Width & Height</button>
+ <button onclick="sizeDefault()">DefaultSize</button><br><br>
+ <div id="grid" dojoType="dojox.Grid" autoWidth="true" autoHeight="true" model="model" structure="structure" elasticView="2"></div>
+
+ <p>Grid fits to a sized container by default:</p>
+ <div id="container">
+ <div id="grid1" dojoType="dojox.VirtualGrid" get="get" structure="structure" rowCount="10" elasticView="2"></div>
+ </div>
+
+ <p> Grid is essentially hidden (height of zero) when parent container is unsized
+ (nothing, including the header, should be displayed):</p>
+ <div id="unsizedContainer">
+ <div id="grid2" dojoType="dojox.VirtualGrid" get="get" structure="structure" rowCount="10" elasticView="2"></div>
+ </div>
+
+ <p> Grid is autoHeight and autoWidth via markup</p>
+ <div id="grid3" dojoType="dojox.VirtualGrid" autoWidth="true" autoHeight="true" get="get" structure="structure" rowCount="10" elasticView="2"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_sizing_100rows.html b/includes/js/dojox/grid/tests/test_sizing_100rows.html
new file mode 100644
index 0000000..4ea1aa3
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_sizing_100rows.html
@@ -0,0 +1,168 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid Sizing Example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../../../dojo/resources/dojo.css";
+ @import "../_grid/tundraGrid.css";
+
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #container {
+ width: 400px;
+ height: 200px;
+ border: 4px double #333;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ /*dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");*/
+ </script>
+ <!-- Debugging -->
+ <script type="text/javascript" src="../_grid/lib.js"></script>
+ <script type="text/javascript" src="../_grid/drag.js"></script>
+ <script type="text/javascript" src="../_grid/scroller.js"></script>
+ <script type="text/javascript" src="../_grid/builder.js"></script>
+ <script type="text/javascript" src="../_grid/cell.js"></script>
+ <script type="text/javascript" src="../_grid/layout.js"></script>
+ <script type="text/javascript" src="../_grid/rows.js"></script>
+ <script type="text/javascript" src="../_grid/focus.js"></script>
+ <script type="text/javascript" src="../_grid/selection.js"></script>
+ <script type="text/javascript" src="../_grid/edit.js"></script>
+ <script type="text/javascript" src="../_grid/view.js"></script>
+ <script type="text/javascript" src="../_grid/views.js"></script>
+ <script type="text/javascript" src="../_grid/rowbar.js"></script>
+ <script type="text/javascript" src="../_grid/publicEvents.js"></script>
+ <script type="text/javascript" src="../VirtualGrid.js"></script>
+ <script type="text/javascript" src="../_data/fields.js"></script>
+ <script type="text/javascript" src="../_data/model.js"></script>
+ <script type="text/javascript" src="../_data/editors.js"></script>
+ <script type="text/javascript" src="../Grid.js"></script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ // grid structure
+ // a grid view is a group of columns
+ // a special view providing selection feedback
+ var rowBar = {type: 'dojox.GridRowView', width: '20px'};
+
+ // a view without scrollbars
+ var leftView = {
+ noscroll: true,
+ cells: [[
+ {name: 'Column 0'},
+ {name: 'Column 1'}
+ ]]};
+
+ var middleView = {
+ cells: [[
+ {name: 'Column 2'},
+ {name: 'Column 3'},
+ {name: 'Column 4'},
+ {name: 'Column 5'},
+ {name: 'Column 6'},
+ ]]};
+
+ // a grid structure is an array of views.
+ var structure = [ rowBar, leftView, middleView];
+
+ // get can return data for each cell of the grid
+ function get(inRowIndex) {
+ return [this.index, inRowIndex].join(', ');
+ }
+
+ function resizeInfo() {
+ setTimeout(function() {
+ dojo.byId('gridWidth').value = grid.domNode.clientWidth;
+ dojo.byId('gridHeight').value = grid.domNode.clientHeight;
+ }, 1);
+ }
+
+ function resizeGrid() {
+ grid.autoHeight = false;
+ grid.autoWidth = false;
+ var
+ w = Number(dojo.byId('gridWidth').value),
+ h = Number(dojo.byId('gridHeight').value);
+
+ dojo.contentBox(grid.domNode, {w: w, h: h});
+ grid.update();
+ }
+
+ function fitWidth() {
+ grid.autoWidth = true;
+ grid.autoHeight = false;
+ grid.update();
+ }
+
+ function fitHeight() {
+ grid.autoWidth = false;
+ grid.autoHeight = true;
+ grid.update();
+ }
+
+ function fitBoth() {
+ grid.autoWidth = true;
+ grid.autoHeight = true;
+ grid.update();
+ }
+
+ function sizeDefault() {
+ grid.autoWidth = false;
+ grid.autoHeight = false;
+ grid.domNode.style.width = '';
+ grid.domNode.style.height = 0;
+ grid.update();
+ }
+
+ dojo.addOnLoad(function() {
+ window["grid"] = dijit.byId("grid");
+ dojo.byId('gridWidth').value = 500;
+ dojo.byId('gridHeight').value = 200;
+ dojo.connect(grid, 'update', resizeInfo);
+ resizeGrid();
+ window["grid1"] = dijit.byId("grid1");
+ });
+
+
+</script>
+</head>
+<body class="tundra">
+<div class="heading">dojox.Grid Sizing Test</div>
+ Grid width: <input id="gridWidth" type="text">&nbsp;
+ and height: <input id="gridHeight" type="text">&nbsp;
+ <button onclick="resizeGrid()">Resize Grid</button><br><br>
+ <button onclick="fitWidth()">Fit Data Width</button>&nbsp;
+ <button onclick="fitHeight()">Fit Data Height</button>&nbsp;
+ <button onclick="fitBoth()">Fit Data Width & Height</button>
+ <button onclick="sizeDefault()">DefaultSize</button><br><br>
+ <div id="grid" dojoType="dojox.Grid" autoWidth="true" autoHeight="true" model="model" structure="structure" elasticView="2"></div>
+
+ <p>Grid fits to a sized container by default:</p>
+ <div id="container">
+ <div id="grid1" dojoType="dojox.VirtualGrid" get="get" structure="structure" rowCount="10" elasticView="2"></div>
+ </div>
+
+ <p> Grid is essentially hidden (height of zero) when parent container is unsized
+ (nothing, including the header, should be displayed):</p>
+ <div id="unsizedContainer">
+ <div id="grid2" dojoType="dojox.VirtualGrid" get="get" structure="structure" rowCount="10" elasticView="2"></div>
+ </div>
+
+ <p> Grid is autoHeight and autoWidth via markup</p>
+ <div id="grid3" dojoType="dojox.VirtualGrid" autoWidth="true" autoHeight="true" get="get" structure="structure" rowCount="100" elasticView="2"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_sizing_ResizeHandle.html b/includes/js/dojox/grid/tests/test_sizing_ResizeHandle.html
new file mode 100644
index 0000000..d6809df
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_sizing_ResizeHandle.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid Sizing Example</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+ @import "../_grid/tundraGrid.css";
+ @import "../../layout/resources/ResizeHandle.css";
+
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #bar, #container {
+ width: 400px;
+ height: 200px;
+ border: 4px double #333;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug:false, parseOnLoad: true"></script>
+
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ dojo.require("dojox.layout.ResizeHandle");
+ </script>
+ <script type="text/javascript">
+ data = [
+ [ "normal", false, "new", 'But are not followed by two hexadecimal', 29.91, 10, false ],
+ [ "important", false, "new", 'Because a % sign always indicates', 9.33, -5, false ],
+ [ "important", false, "read", 'Signs can be selectively', 19.34, 0, true ],
+ [ "note", false, "read", 'However the reserved characters', 15.63, 0, true ],
+ [ "normal", false, "replied", 'It is therefore necessary', 24.22, 5.50, true ],
+ [ "important", false, "replied", 'To problems of corruption by', 9.12, -3, true ],
+ [ "note", false, "replied", 'Which would simply be awkward in', 12.15, -4, false ]
+ ];
+ model = new dojox.grid.data.table(null, data);
+
+ // grid structure
+ // a grid view is a group of columns
+ // a special view providing selection feedback
+ var rowBar = {type: 'dojox.GridRowView', width: '20px'};
+
+ // a view without scrollbars
+ var leftView = {
+ noscroll: false,
+ cells: [[
+ {name: 'Column 0'},
+ {name: 'Column 1'}
+ ]]};
+
+ var middleView = {
+ cells: [[
+ {name: 'Column 2'},
+ {name: 'Column 3'},
+ {name: 'Column 4'},
+ {name: 'Column 5'},
+ {name: 'Column 6'},
+ ]]};
+
+ // a grid structure is an array of views.
+ var structure = [ rowBar, leftView, middleView];
+
+ // get can return data for each cell of the grid
+ function get(inRowIndex) {
+ return [this.index, inRowIndex].join(', ');
+ }
+
+ dojo.addOnLoad(function(){
+ var hand = new dojox.layout.ResizeHandle({
+ targetContainer: dojo.byId("bar"),
+ animateSizing: false,
+ onResize: function(e){
+ setTimeout(dojo.hitch(aGrid,"resize",e),25);
+ }
+ },"hand0");
+ });
+
+
+</script>
+</head>
+<body class="tundra">
+<div class="heading">dojox.Grid Sizing Test w/ the experimental dojox.layout.ResizeHandle</div>
+
+ <p>While this test should work, dojox.layout.ResizeHandle is experimental.</p>
+
+ <div id="bar" style="position:relative">
+ <div jsId="aGrid" id="grid" dojoType="dojox.Grid" model="model" structure="structure" elasticView="2"></div>
+ <div id="hand0"></div>
+ </div>
+
+ <p>Grid fits to a sized container by default:</p>
+ <div id="container" style="position:relative">
+ <div jsId="theGrid" id="grid1" dojoType="dojox.VirtualGrid" get="get" structure="structure" rowCount="75" elasticView="2"></div>
+ <div id="hand1" dojoType="dojox.layout.ResizeHandle" targetId="container" onResize="setTimeout(dojo.hitch(theGrid,'update'),50)" animateSizing="false"></div>
+ </div>
+
+ <p>I am here to take up</p>
+
+ <p>space</p>
+
+ <p>as much as needed.</p>
+
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_styling.html b/includes/js/dojox/grid/tests/test_styling.html
new file mode 100644
index 0000000..5671f50
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_styling.html
@@ -0,0 +1,131 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid Styling Test</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style type="text/css">
+ @import "../_grid/Grid.css";
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .heading {
+ font-weight: bold;
+ padding-bottom: 0.25em;
+ }
+
+ #grid {
+ border: 1px solid #333;
+ width: 45em;
+ height: 30em;
+ }
+
+ #grid .dojoxGrid-row {
+ border: none;
+ }
+
+ #grid .dojoxGrid-row-table {
+ border-collapse: collapse;
+ }
+
+ #grid .dojoxGrid-cell {
+ border: none;
+ padding: 10px;
+ }
+
+ .selectedRow .dojoxGrid-cell {
+ background-color: #003366;
+ color: white;
+ }
+
+ .specialRow .dojoxGrid-cell {
+ background-color: dimgray;
+ }
+
+ .selectedRow.specialRow .dojoxGrid-cell {
+ text-decoration: line-through;
+ /* duplicate selection background-color so has precendence over specialRow background-color */
+ background-color: #003366;
+ }
+
+ /* in the yellow column, assign specific decoration for special rows that are selected */
+ .selectedRow.specialRow .yellowColumnData {
+ text-decoration: line-through underline;
+ }
+
+ .yellowColumn {
+ color: #006666;
+ }
+
+ .overRow .dojoxGrid-cell {
+ text-decoration: underline;
+ }
+
+ .greenColumn {
+ color: yellow;
+ background-color: #006666;
+ font-style: italic;
+ }
+ .yellowColumnData {
+ background-color: yellow;
+ text-decoration: underline;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript" src="support/test_data.js"></script>
+ <script type="text/javascript">
+ // grid structure
+ // a grid view is a group of columns
+
+ // a view without scrollbars
+ var leftView = {
+ noscroll: true,
+ cells: [[
+ {name: 'Column 0', width: 5, headerStyles: 'padding-bottom: 2px;', styles: 'border-bottom: 1px dashed #333; border-right: 1px dashed #333; padding: 6px;'},
+ {name: 'Column 1', width: 5, headerStyles: 'padding-bottom: 2px;', styles: 'text-align: right; border-bottom: 1px dashed #333; border-right: 1px dashed #333; padding: 6px;'}
+ ]]};
+
+ var middleView = {
+ cells: [[
+ {name: 'Column 2'},
+ {name: 'Column 3', headerStyles: 'background-image: none; background-color: #003333;', classes: 'greenColumn'},
+ {name: 'Column 4', cellClasses: 'yellowColumnData', classes: 'yellowColumn', styles: 'text-align: center;' },
+ {name: 'Column 5', headerStyles: 'background-image: none; background-color: #003333;', classes: 'greenColumn'},
+ {name: 'Column 6'},
+ {name: 'Column 7'},
+ ]]};
+
+ // a grid structure is an array of views.
+ var structure = [ leftView, middleView ];
+
+ function onStyleRow(inRow) {
+ with (inRow) {
+ var i = index % 10;
+ var special = (i > 2 && i < 6);
+ if (odd)
+ customStyles += ' color: orange;';
+ if (selected)
+ customClasses += ' selectedRow';
+ if (special)
+ customClasses += ' specialRow';
+ if (over)
+ customClasses += ' overRow';
+ if (!over && !selected)
+ dojox.Grid.prototype.onStyleRow.apply(this, arguments);
+ }
+ }
+
+ dojo.addOnLoad(function() {
+ window["grid"] = dijit.byId('grid');
+ });
+</script>
+</head>
+<body>
+<div class="heading">dojox.Grid Styling Example</div>
+<div id="grid" dojoType="dojox.Grid" onStyleRow="onStyleRow" model="model" structure="structure"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_subgrid.html b/includes/js/dojox/grid/tests/test_subgrid.html
new file mode 100644
index 0000000..4e5b8cd
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_subgrid.html
@@ -0,0 +1,179 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>dojox.Grid Subgrid Test</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</meta>
+<style>
+ @import "../../../dojo/resources/dojo.css";
+ @import "../_grid/tundraGrid.css";
+
+ body { font-size: 1.0em; }
+ #grid {
+ height: 400px;
+ border: 1px solid silver;
+ }
+ .text-oneline {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ .text-scrolling {
+ height: 4em;
+ overflow: auto;
+ }
+ .text-scrolling {
+ width: 21.5em;
+ }
+ </style>
+
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug:true, debugAtAllCosts: false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript">
+ data = [
+ [ '3 stars', 'Averagia', 'Averagia', 8.99, 'An authentic experience defined by the intense layer of frothy, real facts. This combination package includes special T DISCS that work with your system to produce a perfectly serene experience. $8.99 per package. Please choose Regular (#NS1) or Decaffeinated (#NS4).' ],
+ [ '2 stars', 'Cheapy', 'Cheapy', 6.29, 'Power and subtlety intersect for an experience with real character. Imported from Europe just for you. 16 T DISCS per package. $6.29 per package. #NJ4.' ],
+ [ '4 stars', 'Luxuria', 'Luxuria', 6.49, 'A bold statement from the respected European brand Luxuria, topped with delicate zanthum. Imported exclusively for you. 18 T DISCS per package. $6.49 per package. #N42.</div>' ],
+ [ '5 stars', 'Ultimo', 'Ultimo', 4.59, "A rich sensation of delicious experience, brought to you by one of Europe's oldest brands. A pure indulgence. 8 T DISCS per package. $4.59 per package. #NJ0." ]
+ ];
+
+ getDetailData = function(inRowIndex) {
+ var row = data[this.grid.dataRow % data.length];
+ switch (this.index) {
+ case 0:
+ return row[0]; //'<img src="images/sample/' + row[0] + '" width="109" height="75">';
+ case 1:
+ return (100000000 + this.grid.dataRow).toString().slice(1);
+ case 2:
+ return row[3];
+ case 3:
+ return row[1];
+ case 4:
+ return row[2];
+ case 5:
+ return row[4];
+ default:
+ return row[this.index];
+ }
+ }
+
+ getName = function(inRowIndex) {
+ var row = data[inRowIndex % data.length];
+ return row[2];
+ }
+
+ // Main grid structure
+ var gridCells = [
+ { type: 'dojox.GridRowView', width: '20px' },
+ {
+ onBeforeRow: function(inDataIndex, inSubRows) {
+ inSubRows[1].hidden = !detailRows[inDataIndex];
+ },
+ cells: [[
+ { name: '', width: 3, get: getCheck, styles: 'text-align: center;' }, { name: 'Name', get: getName, width: 40 },
+ ], [
+ { name: '', get: getDetail, colSpan: 2, styles: 'padding: 0; margin: 0;'}
+ ]]
+ }
+ ];
+
+ // html for the +/- cell
+ function getCheck(inRowIndex) {
+ var image = (detailRows[inRowIndex] ? 'open.gif' : 'closed.gif');
+ var show = (detailRows[inRowIndex] ? 'false' : 'true')
+ return '<img height="11" width="11" src="images/' + image + '" onclick="toggleDetail(' + inRowIndex + ', ' + show + ')">';
+ }
+
+ // provide html for the Detail cell in the master grid
+ function getDetail(inRowIndex) {
+ var cell = this;
+ // we can affect styles and content here, but we have to wait to access actual nodes
+ setTimeout(function() { buildSubgrid(inRowIndex, cell); }, 1);
+ // look for a subgrid
+ var subGrid = dijit.byId(makeSubgridId(inRowIndex));
+ var h = (subGrid ? subGrid.cacheHeight : "120") + "px";
+ // insert a placeholder
+ return '<div style="height: ' + h + '; background-color: white;"></div>';
+ }
+
+ // the Detail cell contains a subgrid which we set up below
+
+ var subGridCells = [{
+ noscroll: true,
+ cells: [
+ [{ name: "Rating", rowSpan: 2, width: 10, noresize: true, styles: 'text-align:center;' },
+ { name: "Sku" },
+ { name: "Price" },
+ { name: "Vendor" },
+ { name: "Name", width: "auto" }],
+ [{ name: "Description", colSpan: 4 }]
+ ]}];
+
+ var subGridProps = {
+ structure: subGridCells,
+ rowCount: 1,
+ autoHeight: true,
+ autoRender: false,
+ "get": getDetailData
+ };
+
+ // identify subgrids by their row indices
+ function makeSubgridId(inRowIndex) {
+ return grid.widgetId + "_subGrid_" + inRowIndex;
+ }
+
+ // if a subgrid exists at inRowIndex, detach it from the DOM
+ function detachSubgrid(inRowIndex) {
+ var subGrid = dijit.byId(makeSubgridId(inRowIndex));
+ if (subGrid)
+ dojox.grid.removeNode(subGrid.domNode);
+ }
+
+ // render a subgrid into inCell at inRowIndex
+ function buildSubgrid(inRowIndex, inCell) {
+ var n = inCell.getNode(inRowIndex).firstChild;
+ var id = makeSubgridId(inRowIndex);
+ var subGrid = dijit.byId(id);
+ if (subGrid) {
+ n.appendChild(subGrid.domNode);
+ } else {
+ subGridProps.dataRow = inRowIndex;
+ subGridProps.widgetId = id;
+ subGrid = new dojox.VirtualGrid(subGridProps, n);
+ }
+ if (subGrid) {
+ subGrid.render();
+ subGrid.cacheHeight = subGrid.domNode.offsetHeight;
+ inCell.grid.rowHeightChanged(inRowIndex);
+ }
+ }
+
+ // destroy subgrid at inRowIndex
+ function destroySubgrid(inRowIndex) {
+ var subGrid = dijit.byId(makeSubgridId(inRowIndex));
+ if (subGrid) subGrid.destroy();
+ }
+
+ // when user clicks the +/-
+ detailRows = [];
+ function toggleDetail(inIndex, inShow) {
+ if (!inShow) detachSubgrid(inIndex);
+ detailRows[inIndex] = inShow;
+ grid.updateRow(inIndex);
+ }
+
+ dojo.addOnLoad(function() {
+ window["grid"] = dijit.byId("grid");
+ dojo.connect(grid, 'rowRemoved', destroySubgrid);
+ });
+ </script>
+</head>
+<body class="tundra">
+ <div style="font-weight: bold; padding-bottom: 0.25em;">dojox.Grid showing sub-grid.</div>
+ <div id="grid" dojoType="dojox.VirtualGrid" structure="gridCells" rowCount="100000" autoWidth="true"></div>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_tundra_edit.html b/includes/js/dojox/grid/tests/test_tundra_edit.html
new file mode 100644
index 0000000..0aa2eeb
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_tundra_edit.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Test dojox.Grid Editing</title>
+ <style>
+ @import "../_grid/tundraGrid.css";
+ @import "../../../dojo/resources/dojo.css";
+ @import "../../../dijit/themes/tundra/tundra.css";
+ @import "../../../dijit/tests/css/dijitTests.css";
+
+ .dojoxGrid-row-editing td {
+ background-color: #F4FFF4;
+ }
+ .dojoxGrid input, .dojoxGrid select, .dojoxGrid textarea {
+ margin: 0;
+ padding: 0;
+ border-style: none;
+ width: 100%;
+ font-size: 100%;
+ font-family: inherit;
+ }
+ .dojoxGrid input {
+ }
+ .dojoxGrid select {
+ }
+ .dojoxGrid textarea {
+ }
+
+ #controls {
+ padding: 6px 0;
+ }
+ #controls button {
+ margin-left: 10px;
+ }
+ .myGrid {
+ width: 850px;
+ height: 350px;
+ border: 1px solid silver;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug:false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript">
+ // ==========================================================================
+ // Create a data model
+ // ==========================================================================
+ data = [
+ [ "normal", false, "new", 'But are not followed by two hexadecimal', 29.91, 10, false ],
+ [ "important", false, "new", 'Because a % sign always indicates', 9.33, -5, false ],
+ [ "important", false, "read", 'Signs can be selectively', 19.34, 0, true ],
+ [ "note", false, "read", 'However the reserved characters', 15.63, 0, true ],
+ [ "normal", false, "replied", 'It is therefore necessary', 24.22, 5.50, true ],
+ [ "important", false, "replied", 'To problems of corruption by', 9.12, -3, true ],
+ [ "note", false, "replied", 'Which would simply be awkward in', 12.15, -4, false ]
+ ];
+ var rows = 10000;
+ for(var i=0, l=data.length; i<rows-l; i++){
+ data.push(data[i%l].slice(0));
+ }
+ model = new dojox.grid.data.Table(null, data);
+
+ // ==========================================================================
+ // Tie some UI to the data model
+ // ==========================================================================
+ model.observer(this);
+ modelChange = function(){
+ dojo.byId("rowCount").innerHTML = 'Row count: ' + model.count;
+ }
+
+ // ==========================================================================
+ // Custom formatter
+ // ==========================================================================
+ formatMoney = function(inDatum){
+ return isNaN(inDatum) ? '...' : '$' + parseFloat(inDatum).toFixed(2);
+ }
+
+ // ==========================================================================
+ // Grid structure
+ // ==========================================================================
+ statusCell = {
+ field: 2,
+ name: 'Status',
+ styles: 'text-align: center;',
+ editor: dojox.grid.editors.Select,
+ options: [ "new", "read", "replied" ]
+ };
+
+ gridLayout = [
+ {
+ type: 'dojox.GridRowView', width: '20px'
+ },
+ {
+ defaultCell: { width: 8, editor: dojox.grid.editors.Input, styles: 'text-align: right;' },
+ rows: [
+ [
+ { name: 'Id', width: 3, get: function(inRowIndex){ return inRowIndex+1;} },
+ { name: 'Priority', styles: 'text-align: center;', editor: dojox.grid.editors.Select, options: ["normal", "note", "important"]},
+ { name: 'Mark', width: 3, styles: 'text-align: center;', editor: dojox.grid.editors.Bool },
+ statusCell,
+ { name: 'Message', styles: '', width: '100%' },
+ { name: 'Amount', formatter: formatMoney }
+ ]
+ ]
+ }
+ ];
+ // ==========================================================================
+ // UI Action
+ // ==========================================================================
+ addRow = function() {
+ grid.addRow([ "normal", false, "new", 'Now is the time for all good men to come to the aid of their party.', 99.99, 9.99, false ]);
+ }
+ </script>
+ </head>
+ <body class="tundra">
+ <h1>dojox.Grid Basic Editing test</h1>
+ <br />
+ <div id="controls">
+ <button onclick="grid.refresh()">Refresh</button>
+ <button onclick="grid.edit.focusEditor()">Focus Editor</button>
+ <button onclick="grid.focus.next()">Next Focus</button>
+ <button onclick="addRow()">Add Row</button>
+ <button onclick="grid.removeSelectedRows()">Remove</button>
+ <button onclick="grid.edit.apply()">Apply</button>
+ <button onclick="grid.edit.cancel()">Cancel</button>
+ <button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button>
+ </div>
+ <br />
+ <div jsId="grid" class="myGrid"
+ dojoType="dojox.Grid" model="model"
+ structure="gridLayout"></div>
+ <br />
+ <div id="rowCount"></div>
+ </body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_yahoo_images.html b/includes/js/dojox/grid/tests/test_yahoo_images.html
new file mode 100644
index 0000000..fbab070
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_yahoo_images.html
@@ -0,0 +1,148 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid - Image Search Test</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style>
+ @import "../_grid/Grid.css";
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .grid {
+ height: 30em;
+ width: 51em;
+ border: 1px solid silver;
+ }
+ #info { width: 700px; }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="debugAtAllCosts: false, isDebug:false, parseOnLoad: true">
+ </script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript" src="yahooSearch.js"></script>
+ <script type="text/javascript">
+ // model fields
+ imageFields = [
+ { name: 'Title', na: '' },
+ { name: 'Thumbnail', na: ''},
+ { name: 'Summary', na: '' },
+ { name: 'Url', na: '' },
+ { name: 'FileSize', na: ''},
+ { name: 'Height', na: ''},
+ { name: 'Width', na: ''}
+ ];
+ // create data model
+ var model = new dojox.grid.data.yahooSearch(imageFields, null, "searchInput");
+ model.url = 'http://search.yahooapis.com/ImageSearchService/V1/imageSearch';
+ model.observer(this);
+
+ // report some model send/receive status
+ model.onSend = function(inParams){
+ dojo.byId('sendInfo').innerHTML = dojo.string.substitute(
+ 'Request rows ${0} to ${1}.&nbsp&nbsp;',
+ [inParams.start, inParams.start + inParams.results -1]
+ );
+ }
+ model.onReceive = function(inData) {
+ dojo.byId('receiveInfo').innerHTML = dojo.string.substitute(
+ 'Receive rows ${0} to ${1}.&nbsp&nbsp;',
+ [
+ inData.firstResultPosition,
+ inData.firstResultPosition + inData.totalResultsReturned-1
+ ]
+ );
+ }
+
+
+ // Define grid structure
+ // remove the height from the header image cell / row cells have a default height so there's less adjustment when thumb comes in.
+ beforeImageRow = function(inRowIndex, inSubRows){
+ inSubRows[0].hidden = (inRowIndex == -1);
+ }
+
+ var imageLayout = [
+ { onBeforeRow: beforeImageRow,
+ cells: [
+ [ { name: 'Image', cellStyles: "height: 100px;", styles: "text-align: center;", width: 12, field: 3, extraField: 1, formatter: formatImage },
+ { name: 'Image', cellStyles: "height: 100px;", styles: "text-align: center;", width: 12, field: 3, extraField: 1, formatter: formatImage },
+ { name: 'Image', cellStyles: "height: 100px;", styles: "text-align: center;", width: 12, field: 3, extraField: 1, formatter: formatImage },
+ { name: 'Image', cellStyles: "height: 100px;", styles: "text-align: center;", width: 12, field: 3, extraField: 1, formatter: formatImage }
+ ]
+ ]}
+ ];
+
+ // Create grid subclass to function as we need to display images only.
+ // adds indirection between model row and grid row.
+ dojo.declare("dojox.ImageGrid", dojox.Grid, {
+ postCreate: function() {
+ this.inherited(arguments);
+ this.modelDatumChange = this.modelRowChange;
+ this.colCount = this.layout.cells.length;
+ },
+ getDataRowIndex: function(inCell, inRowIndex) {
+ var r = inCell.index + Math.floor(inRowIndex * this.colCount);
+ return r;
+ },
+ // called in cell context
+ get: function(inRowIndex) {
+ var r = this.grid.getDataRowIndex(this, inRowIndex);
+ return dojox.Grid.prototype.get.call(this, r);
+ },
+ modelAllChange: function(){
+ this.rowCount = Math.ceil(this.model.getRowCount() / this.colCount);
+ this.updateRowCount(this.rowCount);
+ },
+ modelRowChange: function(inData, inRowIndex) {
+ if(
+ (inRowIndex % this.colCount == this.colCount - 1)||
+ (inRowIndex == this.model.count - 1)
+ ){
+ this.updateRow(Math.floor(inRowIndex / this.colCount));
+ }
+ }
+ });
+
+ getCellData = function(inCell, inRowIndex, inField) {
+ var m = inCell.grid.model, r = inCell.grid.getDataRowIndex(inCell, inRowIndex);
+ return m.getDatum(r, inField);
+ }
+
+ // execute search
+ doSearch = function(){
+ model.clearData();
+ model.setRowCount(0);
+ grid.render();
+ grid.resize();
+ model.requestRows();
+ }
+
+ dojo.addOnLoad(function(){
+ dojo.query("#searchInput").onkeypress(function(e){
+ if(e.keyCode == dojo.keys.ENTER){ doSearch(); }
+ });
+ doSearch();
+ });
+
+ </script>
+</head>
+<body>
+ <div style="font-weight: bold; padding-bottom: 0.25em;">dojox.Grid - Image Search Test</div>
+ <input id="searchInput" type="text" value="apple">
+ <button onclick="doSearch()" style="clear: both;">Search</button>
+ <div jsId="grid" class="grid" structure="imageLayout" dojoType="dojox.ImageGrid" model="model"></div>
+ <br>
+ <div id="info">
+ <div id="rowCount" style="float: left"></div>
+ <div style="float: right">
+ <div id="sendInfo" style="text-align: right"></div>
+ <div id="receiveInfo" style="text-align: right"></div>
+ </div>
+ </div>
+ <br /><br />
+ <p>Note: requires PHP for proxy.</p>
+ </body>
+</html>
diff --git a/includes/js/dojox/grid/tests/test_yahoo_search.html b/includes/js/dojox/grid/tests/test_yahoo_search.html
new file mode 100644
index 0000000..063c289
--- /dev/null
+++ b/includes/js/dojox/grid/tests/test_yahoo_search.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>dojox.Grid - Yahoo Search Test</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+ <style>
+ @import "../_grid/Grid.css";
+ body {
+ font-size: 0.9em;
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+ }
+ .grid {
+ height: 30em;
+ }
+
+ #info {
+ width: 700px;
+ }
+ </style>
+ <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.grid.Grid");
+ dojo.require("dojo.parser");
+ </script>
+ <script type="text/javascript" src="yahooSearch.js"></script>
+ <script type="text/javascript">
+ webFields = [
+ { name: 'Title', na: '' },
+ { name: 'ModificationDate', na: ''},
+ { name: 'Summary', na: '&nbsp;' },
+ { name: 'Url', na: '' },
+ { name: 'MimeType', na: '&nbsp;'},
+ { name: 'DisplayUrl', na: '&nbsp;'}
+ ];
+
+ imageFields = [
+ { name: 'Title', na: '' },
+ { name: 'Thumbnail', na: ''},
+ { name: 'Summary', na: '' },
+ { name: 'Url', na: '' },
+ { name: 'FileSize', na: ''},
+ { name: 'Height', na: ''},
+ { name: 'Width', na: ''}
+ ];
+
+ var model = new dojox.grid.data.yahooSearch(imageFields, null, "searchInput");
+ model.observer(this);
+ // report some model send/receive status
+ model.onSend = function(inParams) {
+ dojo.byId('sendInfo').innerHTML = dojo.string.substitute('Request rows ${0} to ${1}.&nbsp&nbsp;', [inParams.start, inParams.start + inParams.results -1] );
+ }
+ model.onReceive = function(inData) {
+ dojo.byId('receiveInfo').innerHTML = dojo.string.substitute('Receive rows ${0} to ${1}.&nbsp&nbsp;', [inData.firstResultPosition, inData.firstResultPosition + inData.totalResultsReturned-1]);
+ }
+
+
+ var webLayout = [
+ { type: 'dojox.GridRowView', width: '20px' },
+ { noscroll: true,
+ cells: [
+ [ { name: 'Row', width: 3, styles: 'text-align: center;', get: function(inRowIndex) { return inRowIndex + 1 } }]
+ ]
+ },
+ { cells: [
+ [ { name: 'Site', width: 30, field: 3, extraField: 0, formatter: formatLink }, { name: 'Date', width: 10, field: 1, formatter: formatDate} ],
+ [ { name: 'Display Url', width: 30, field: 5, styles: 'color: green; size: small;' }, { name: 'Type', width: 10, field: 4, styles: ' font-style: italic; color: gray; size: small;'} ],
+ [ { name: 'Summary', width: 40, colSpan: 2, field: 2 } ]
+ ]}
+ ];
+
+ // remove the height from the header image cell / row cells have a default height so there's less adjustment when thumb comes in.
+ beforeImageRow = function(inRowIndex, inSubRow) {
+ inSubRow[0][0].cellStyles = (inRowIndex == -1 ? '' : 'height: 100px;');
+ inSubRow[1][0].cellStyles = (inRowIndex == -1 ? '' : 'vertical-align: top; height: 75px;');
+ }
+
+ var imageLayout = [
+ { type: 'dojox.GridRowView', width: '20px' },
+ { noscroll: true,
+ cells: [
+ [ { name: 'Row', width: 3, styles: 'text-align: center;', get: function(inRowIndex) { return inRowIndex + 1 } }]
+ ]
+ },
+ { onBeforeRow: beforeImageRow,
+ cells: [
+ [ { name: 'Image', cellStyles: "height: 100px;", styles: "text-align: center;", width: 13, rowSpan: 2, field: 3, extraField: 1, formatter: formatImage },
+ { name: 'Title', cellStyles: "height: 10px;", width: 14, field: 3, extraField: 0, formatter: formatLink },
+ { name: 'Size', width: 8, field: 4, styles: "font-style: italic; text-align: center;" },
+ { name: 'Dimensions', width: 8, field: 6, extraField: 5, styles: "text-align: center;", formatter: formatDimensions }
+ ],
+ [ { name: 'Summary', cellStyles: "vertical-align: top; height: 75px;", colSpan: 3, field: 2 } ]
+ ]}
+ ];
+
+ // execute search
+ doSearch = function() {
+ var web = dojo.byId('webRb').checked;
+ model.setRowCount(0);
+ model.clear();
+ model.fields.set(web ? webFields : imageFields);
+ model.url = 'http://search.yahooapis.com/' + (web ? 'WebSearchService/V1/webSearch' : 'ImageSearchService/V1/imageSearch');
+ grid.scrollToRow(0);
+ grid.setStructure(web ? webLayout : imageLayout);
+ model.requestRows();
+ }
+
+ // do search on enter...
+ keypress = function(e) {
+ if (e.keyCode == dojo.keys.ENTER)
+ doSearch();
+ }
+
+ dojo.addOnLoad(function() {
+ dojo.byId('webRb').checked = "checked";
+ dojo.connect(dojo.byId("searchInput"), "keypress", keypress);
+ doSearch();
+ });
+
+ </script>
+</head>
+<body>
+<div style="font-weight: bold; padding-bottom: 0.25em;">dojox.Grid - Yahoo Search Test</div>
+<div style="padding-bottom: 3px;">
+ <label><input id="webRb" type="radio" name="searchType" checked>Web</label>&nbsp;&nbsp;
+ <label><input id="imageRb" type="radio" name="searchType">Images</label>
+</div>
+<input id="searchInput" type="text" value="apple">&nbsp;&nbsp;
+<button onclick="doSearch()">Search</button><br><br>
+<div jsId="grid" class="grid" autoWidth="true" structure="webLayout" dojoType="dojox.Grid" model="model" elasticView="1"></div>
+<br>
+<div id="info">
+ <div id="rowCount" style="float: left"></div>
+ <div style="float: right">
+ <div id="sendInfo" style="text-align: right"></div>
+ <div id="receiveInfo" style="text-align: right"></div>
+ </div>
+</div>
+<br /><br />
+<p>Note: requires PHP for proxy.</p>
+</body>
+</html>
diff --git a/includes/js/dojox/grid/tests/yahooSearch.js b/includes/js/dojox/grid/tests/yahooSearch.js
new file mode 100644
index 0000000..1d57a8e
--- /dev/null
+++ b/includes/js/dojox/grid/tests/yahooSearch.js
@@ -0,0 +1,137 @@
+dojo.require("dojo.io.script")
+dojo.require("dojox.rpc.Service");
+
+// model that works with Yahoo Search API
+dojo.declare("dojox.grid.data.yahooSearch", dojox.grid.data.Dynamic, {
+ constructor: function(inFields, inData, inSearchNode){
+ this.rowsPerPage = 20;
+ this.searchNode = inSearchNode;
+ this.fieldNames = dojo.map(inFields, "return item.name;");
+ this.yahoo = new dojox.rpc.Service(
+ dojo.moduleUrl("dojox.rpc.SMDLibrary", "yahoo.smd")
+ );
+ },
+ // server send / receive
+ send: function(inAsync, inParams, inOnReceive, inOnError){
+ var d = this.yahoo.imageSearch(
+ dojo.mixin({
+ results: this.rowsPerPage,
+ query: this.getQuery()
+ }, inParams)
+ );
+ d.addCallbacks(
+ dojo.hitch(this, "receive", inOnReceive, inOnError),
+ dojo.hitch(this, "error", inOnError)
+ );
+ this.onSend(inParams);
+ return d;
+ },
+ receive: function(inOnReceive, inOnError, inData){
+ try{
+ inData = inData.ResultSet;
+ inOnReceive(inData);
+ this.onReceive(inData);
+ }catch(e){
+ if(inOnError){
+ inOnError(inData);
+ }
+ }
+ },
+ error: function(inOnError, inErr) {
+ var m = 'io error: ' + inErr.message;
+ alert(m);
+ if (inOnError)
+ inOnError(m);
+ },
+ encodeParam: function(inName, inValue) {
+ return dojo.string.substitute('&${0}=${1}', [inName, inValue]);
+ },
+ getQuery: function(){
+ return dojo.byId(this.searchNode).value.replace(/ /g, '+');
+ },
+ fetchRowCount: function(inCallback){
+ this.send(true, inCallback);
+ },
+ // request data
+ requestRows: function(inRowIndex, inCount){
+ inRowIndex = (inRowIndex == undefined ? 0 : inRowIndex);
+ var params = {
+ start: inRowIndex + 1
+ }
+ this.send(true, params, dojo.hitch(this, this.processRows));
+ },
+ // server callbacks
+ processRows: function(inData){
+ for(var i=0, l=inData.totalResultsReturned, s=inData.firstResultPosition; i<l; i++){
+ this.setRow(inData.Result[i], s - 1 + i);
+ }
+ // yahoo says 1000 is max results to return
+ var c = Math.min(1000, inData.totalResultsAvailable);
+ if(this.count != c){
+ this.setRowCount(c);
+ this.allChange();
+ this.onInitializeData(inData);
+ }
+ },
+ getDatum: function(inRowIndex, inColIndex){
+ var row = this.getRow(inRowIndex);
+ var field = this.fields.get(inColIndex);
+ return (inColIndex == undefined ? row : (row ? row[field.name] : field.na));
+ },
+ // events
+ onInitializeData: function(){ },
+ onSend: function(){ },
+ onReceive: function(){ }
+});
+
+// report
+modelChange = function(){
+ var n = dojo.byId('rowCount');
+ if(n){
+ n.innerHTML = dojo.string.substitute('about ${0} row(s)', [model.count]);
+ }
+}
+
+
+// some data formatters
+getCellData = function(inCell, inRowIndex, inField){
+ var m = inCell.grid.model;
+ return m.getDatum(inRowIndex, inField);
+}
+
+formatLink = function(inData, inRowIndex){
+ if(!inData){ return '&nbsp;'; }
+ var text = getCellData(this, inRowIndex, this.extraField);
+ return dojo.string.substitute(
+ '<a target="_blank" href="${href}">${text}</a>',
+ { href: inData, text: text }
+ );
+};
+
+formatImage = function(inData, inRowIndex){
+ if(!inData){ return '&nbsp;'; }
+ var info = getCellData(this, inRowIndex, this.extraField);
+ var o = {
+ href: inData,
+ src: info.Url,
+ width: info.Width,
+ height: info.Height
+ }
+ return dojo.string.substitute(
+ '<a href="${href}" target="_blank"><img border=0 src="${src}" width="${width}" height="${height}"></a>', o);
+};
+
+formatDate = function(inDatum, inRowIndex){
+ if(!inDatum){ return '&nbsp;'; }
+ var d = new Date(inDatum * 1000);
+ return dojo.string.substitute(
+ "${0}/${1}/${2}",
+ [ d.getMonth()+1, d.getDate(), d.getFullYear() ]
+ );
+};
+
+formatDimensions = function(inData, inRowIndex){
+ if(!inData){ return '&nbsp;'; }
+ var w = inData, h = getCellData(this, inRowIndex, this.extraField);
+ return w + ' x ' + h;
+}