diff options
author | mensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f> | 2008-11-13 09:49:11 +0000 |
---|---|---|
committer | mensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f> | 2008-11-13 09:49:11 +0000 |
commit | e44a7e37b6c7b5961adaffc62b9042b8d442938e (patch) | |
tree | 95b67c356e93163467db2451f2b8cce84ed5d582 /includes/js/dojox/grid | |
parent | a62b9742ee5e28bcec6872d88f50f25b820914f6 (diff) | |
download | semanticscuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.gz semanticscuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.bz2 |
New feature: basic Ajax suggestion for tags and implementation of Dojo toolkit
git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@151 b3834d28-1941-0410-a4f8-b48e95affb8f
Diffstat (limited to 'includes/js/dojox/grid')
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 Binary files differnew file mode 100644 index 0000000..57f67ba --- /dev/null +++ b/includes/js/dojox/grid/_grid/images/grid_dx_gradient.gif diff --git a/includes/js/dojox/grid/_grid/images/grid_sort_down.gif b/includes/js/dojox/grid/_grid/images/grid_sort_down.gif Binary files differnew file mode 100644 index 0000000..7a73f82 --- /dev/null +++ b/includes/js/dojox/grid/_grid/images/grid_sort_down.gif diff --git a/includes/js/dojox/grid/_grid/images/grid_sort_up.gif b/includes/js/dojox/grid/_grid/images/grid_sort_up.gif Binary files differnew file mode 100644 index 0000000..9452da0 --- /dev/null +++ b/includes/js/dojox/grid/_grid/images/grid_sort_up.gif diff --git a/includes/js/dojox/grid/_grid/images/tabEnabled_rotated.png b/includes/js/dojox/grid/_grid/images/tabEnabled_rotated.png Binary files differnew file mode 100644 index 0000000..e326abd --- /dev/null +++ b/includes/js/dojox/grid/_grid/images/tabEnabled_rotated.png diff --git a/includes/js/dojox/grid/_grid/images/tabHover_rotated.png b/includes/js/dojox/grid/_grid/images/tabHover_rotated.png Binary files differnew file mode 100644 index 0000000..1a30e10 --- /dev/null +++ b/includes/js/dojox/grid/_grid/images/tabHover_rotated.png 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 ? '▼' : '▲', '</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 Binary files differnew file mode 100644 index 0000000..7d3afa4 --- /dev/null +++ b/includes/js/dojox/grid/tests/images/closed.gif diff --git a/includes/js/dojox/grid/tests/images/flatScreen.gif b/includes/js/dojox/grid/tests/images/flatScreen.gif Binary files differnew file mode 100644 index 0000000..05edd72 --- /dev/null +++ b/includes/js/dojox/grid/tests/images/flatScreen.gif diff --git a/includes/js/dojox/grid/tests/images/open.gif b/includes/js/dojox/grid/tests/images/open.gif Binary files differnew file mode 100644 index 0000000..37efd2c --- /dev/null +++ b/includes/js/dojox/grid/tests/images/open.gif 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 ' '; + 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 ' '; + 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 ' '; + 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 ' '; + 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> + <button onclick="dataModel.clearData(true)">Clear Data (Model)</button> + <button onclick="dataModel.refresh()">Refresh (Model)</button> + <button onclick="grid.edit.focusEditor()">Focus Editor</button> + <button onclick="grid.focus.next()">Next Focus</button> + <button onclick="addItem()">Add</button> + <button onclick="grid.removeSelectedRows()">Remove</button> + <button onclick="jsonStore.revert()">Revert (Store)</button> + <button onclick="removeItem()">Remove (Store)</button> + <button onclick="addItemToStore()">Add (Store)</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> +<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> + <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" 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>
+ <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" 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">
+ <input type="button" onclick="toggleMenu(this)" value="Disable Grid Menu"> <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> + <button onclick="removeSelected()">Remove Selected</button> + <button onclick="grid.edit.apply()">Apply Edit</button> + <button onclick="grid.edit.cancel()">Cancel Edit</button> + <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"> + and height: <input id="gridHeight" type="text"> + <button onclick="resizeGrid()">Resize Grid</button><br><br> + <button onclick="fitWidth()">Fit Data Width</button> + <button onclick="fitHeight()">Fit Data Height</button> + <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">
+ and height: <input id="gridHeight" type="text">
+ <button onclick="resizeGrid()">Resize Grid</button><br><br>
+ <button onclick="fitWidth()">Fit Data Width</button>
+ <button onclick="fitHeight()">Fit Data Height</button>
+ <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}.  ', + [inParams.start, inParams.start + inParams.results -1] + ); + } + model.onReceive = function(inData) { + dojo.byId('receiveInfo').innerHTML = dojo.string.substitute( + 'Receive rows ${0} to ${1}.  ', + [ + 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: ' ' }, + { name: 'Url', na: '' }, + { name: 'MimeType', na: ' '}, + { name: 'DisplayUrl', na: ' '} + ]; + + 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}.  ', [inParams.start, inParams.start + inParams.results -1] ); + } + model.onReceive = function(inData) { + dojo.byId('receiveInfo').innerHTML = dojo.string.substitute('Receive rows ${0} to ${1}.  ', [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> + <label><input id="imageRb" type="radio" name="searchType">Images</label> +</div> +<input id="searchInput" type="text" value="apple"> +<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 ' '; } + 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 ' '; } + 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 ' '; } + 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 ' '; } + var w = inData, h = getCellData(this, inRowIndex, this.extraField); + return w + ' x ' + h; +} |