]> git.pond.sub.org Git - eow/blobdiff - static/dojo-release-1.1.1/dojox/grid/Grid.js
add Dojo 1.1.1
[eow] / static / dojo-release-1.1.1 / dojox / grid / Grid.js
diff --git a/static/dojo-release-1.1.1/dojox/grid/Grid.js b/static/dojo-release-1.1.1/dojox/grid/Grid.js
new file mode 100644 (file)
index 0000000..309bb25
--- /dev/null
@@ -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;
+
+}