]> git.pond.sub.org Git - eow/blob - static/dojo-release-1.1.1/dojox/grid/_data/model.js
add Dojo 1.1.1
[eow] / static / dojo-release-1.1.1 / dojox / grid / _data / model.js
1 if(!dojo._hasResource['dojox.grid._data.model']){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource['dojox.grid._data.model'] = true;
3 dojo.provide('dojox.grid._data.model');
4 dojo.require('dojox.grid._data.fields');
5
6 dojo.declare("dojox.grid.data.Model", null, {
7         // summary:
8         //      Base abstract grid data model.
9         //      Makes no assumptions about the structure of grid data.
10         constructor: function(inFields, inData){
11                 this.observers = [];
12                 this.fields = new dojox.grid.data.Fields();
13                 if(inFields){
14                         this.fields.set(inFields);
15                 }
16                 this.setData(inData);
17         },
18         count: 0,
19         updating: 0,
20         // observers 
21         observer: function(inObserver, inPrefix){
22                 this.observers.push({o: inObserver, p: inPrefix||'model' });
23         },
24         notObserver: function(inObserver){
25                 for(var i=0, m, o; (o=this.observers[i]); i++){
26                         if(o.o==inObserver){
27                                 this.observers.splice(i, 1);
28                                 return;
29                         }
30                 }
31         },
32         notify: function(inMsg, inArgs){
33                 if(!this.isUpdating()){
34                         var a = inArgs || [];
35                         for(var i=0, m, o; (o=this.observers[i]); i++){
36                                 m = o.p + inMsg; o = o.o;
37                                 (m in o)&&(o[m].apply(o, a));
38                         }
39                 }
40         },
41         // updates
42         clear: function(){
43                 this.fields.clear();
44                 this.clearData();
45         },
46         beginUpdate: function(){
47                 this.updating++;
48         },
49         endUpdate: function(){
50                 if(this.updating){
51                         this.updating--;
52                 }
53                 /*if(this.updating){
54                         if(!(--this.updating)){
55                                 this.change();
56                         }
57                 }
58                 }*/
59         },
60         isUpdating: function(){
61                 return Boolean(this.updating);
62         },
63         // data
64         clearData: function(){
65                 this.setData(null);
66         },
67         // observer events
68         change: function(){
69                 this.notify("Change", arguments);
70         },
71         insertion: function(/* index */){
72                 this.notify("Insertion", arguments);
73                 this.notify("Change", arguments);
74         },
75         removal: function(/* keys */){
76                 this.notify("Removal", arguments);
77                 this.notify("Change", arguments);
78         },
79         // insert
80         insert: function(inData /*, index */){
81                 if(!this._insert.apply(this, arguments)){
82                         return false;
83                 }
84                 this.insertion.apply(this, dojo._toArray(arguments, 1));
85                 return true;
86         },
87         // remove
88         remove: function(inData /*, index */){
89                 if(!this._remove.apply(this, arguments)){
90                         return false;
91                 }
92                 this.removal.apply(this, arguments);
93                 return true;
94         },
95         // sort
96         canSort: function(/* (+|-)column_index+1, ... */){
97                 return this.sort != null;
98         },
99         generateComparator: function(inCompare, inField, inTrueForAscend, inSubCompare){
100                 return function(a, b){
101                         var ineq = inCompare(a[inField], b[inField]);
102                         return ineq ? (inTrueForAscend ? ineq : -ineq) : inSubCompare && inSubCompare(a, b);
103                 }
104         },
105         makeComparator: function(inIndices){
106                 var idx, col, field, result = null;
107                 for(var i=inIndices.length-1; i>=0; i--){
108                         idx = inIndices[i];
109                         col = Math.abs(idx) - 1;
110                         if(col >= 0){
111                                 field = this.fields.get(col);
112                                 result = this.generateComparator(field.compare, field.key, idx > 0, result);
113                         }
114                 }
115                 return result;
116         },
117         sort: null,
118         dummy: 0
119 });
120
121 dojo.declare("dojox.grid.data.Rows", dojox.grid.data.Model, {
122         // observer events
123         allChange: function(){
124                 this.notify("AllChange", arguments);
125                 this.notify("Change", arguments);
126         },
127         rowChange: function(){
128                 this.notify("RowChange", arguments);
129         },
130         datumChange: function(){
131                 this.notify("DatumChange", arguments);
132         },
133         // copyRow: function(inRowIndex); // abstract
134         // update
135         beginModifyRow: function(inRowIndex){
136                 if(!this.cache[inRowIndex]){
137                         this.cache[inRowIndex] = this.copyRow(inRowIndex);
138                 }
139         },
140         endModifyRow: function(inRowIndex){
141                 var cache = this.cache[inRowIndex];
142                 if(cache){
143                         var data = this.getRow(inRowIndex);
144                         if(!dojox.grid.arrayCompare(cache, data)){
145                                 this.update(cache, data, inRowIndex);
146                         }
147                         delete this.cache[inRowIndex];
148                 }
149         },
150         cancelModifyRow: function(inRowIndex){
151                 var cache = this.cache[inRowIndex];
152                 if(cache){
153                         this.setRow(cache, inRowIndex);
154                         delete this.cache[inRowIndex];
155                 }
156         }
157 });
158
159 dojo.declare("dojox.grid.data.Table", dojox.grid.data.Rows, {
160         // summary:
161         //      Basic grid data model for static data in the form of an array of rows
162         //      that are arrays of cell data
163         constructor: function(){
164                 this.cache = [];
165         },
166         colCount: 0, // tables introduce cols
167         data: null,
168         cache: null,
169         // morphology
170         measure: function(){
171                 this.count = this.getRowCount();
172                 this.colCount = this.getColCount();
173                 this.allChange();
174                 //this.notify("Measure");
175         },
176         getRowCount: function(){
177                 return (this.data ? this.data.length : 0);
178         },
179         getColCount: function(){
180                 return (this.data && this.data.length ? this.data[0].length : this.fields.count());
181         },
182         badIndex: function(inCaller, inDescriptor){
183                 console.debug('dojox.grid.data.Table: badIndex');
184         },
185         isGoodIndex: function(inRowIndex, inColIndex){
186                 return (inRowIndex >= 0 && inRowIndex < this.count && (arguments.length < 2 || (inColIndex >= 0 && inColIndex < this.colCount)));
187         },
188         // access
189         getRow: function(inRowIndex){
190                 return this.data[inRowIndex];
191         },
192         copyRow: function(inRowIndex){
193                 return this.getRow(inRowIndex).slice(0);
194         },
195         getDatum: function(inRowIndex, inColIndex){
196                 return this.data[inRowIndex][inColIndex];
197         },
198         get: function(){
199                 throw('Plain "get" no longer supported. Use "getRow" or "getDatum".');
200         },
201         setData: function(inData){
202                 this.data = (inData || []);
203                 this.allChange();
204         },
205         setRow: function(inData, inRowIndex){
206                 this.data[inRowIndex] = inData;
207                 this.rowChange(inData, inRowIndex);
208                 this.change();
209         },
210         setDatum: function(inDatum, inRowIndex, inColIndex){
211                 this.data[inRowIndex][inColIndex] = inDatum;
212                 this.datumChange(inDatum, inRowIndex, inColIndex);
213         },
214         set: function(){
215                 throw('Plain "set" no longer supported. Use "setData", "setRow", or "setDatum".');
216         },
217         setRows: function(inData, inRowIndex){
218                 for(var i=0, l=inData.length, r=inRowIndex; i<l; i++, r++){
219                         this.setRow(inData[i], r);
220                 }
221         },
222         // update
223         update: function(inOldData, inNewData, inRowIndex){
224                 //delete this.cache[inRowIndex];        
225                 //this.setRow(inNewData, inRowIndex);
226                 return true;
227         },
228         // insert
229         _insert: function(inData, inRowIndex){
230                 dojox.grid.arrayInsert(this.data, inRowIndex, inData);
231                 this.count++;
232                 return true;
233         },
234         // remove
235         _remove: function(inKeys){
236                 for(var i=inKeys.length-1; i>=0; i--){
237                         dojox.grid.arrayRemove(this.data, inKeys[i]);
238                 }
239                 this.count -= inKeys.length;
240                 return true;
241         },
242         // sort
243         sort: function(/* (+|-)column_index+1, ... */){
244                 this.data.sort(this.makeComparator(arguments));
245         },
246         swap: function(inIndexA, inIndexB){
247                 dojox.grid.arraySwap(this.data, inIndexA, inIndexB);
248                 this.rowChange(this.getRow(inIndexA), inIndexA);
249                 this.rowChange(this.getRow(inIndexB), inIndexB);
250                 this.change();
251         },
252         dummy: 0
253 });
254
255 dojo.declare("dojox.grid.data.Objects", dojox.grid.data.Table, {
256         constructor: function(inFields, inData, inKey){
257                 if(!inFields){
258                         this.autoAssignFields();
259                 }
260         },
261         allChange: function(){
262                 this.notify("FieldsChange");
263                 this.inherited(arguments);
264         },
265         autoAssignFields: function(){
266                 var d = this.data[0], i = 0, field;
267                 for(var f in d){
268                         field = this.fields.get(i++);
269                         if (!dojo.isString(field.key)){
270                                 field.key = f;
271                         }
272                 }
273         },
274         setData: function(inData){
275                 this.data = (inData || []);
276                 this.autoAssignFields();
277                 this.allChange();
278         },
279         getDatum: function(inRowIndex, inColIndex){
280                 return this.data[inRowIndex][this.fields.get(inColIndex).key];
281         }
282 });
283
284 dojo.declare("dojox.grid.data.Dynamic", dojox.grid.data.Table, {
285         // summary:
286         //      Grid data model for dynamic data such as data retrieved from a server.
287         //      Retrieves data automatically when requested and provides notification when data is received
288         constructor: function(){
289                 this.page = [];
290                 this.pages = [];
291         },
292         page: null,
293         pages: null,
294         rowsPerPage: 100,
295         requests: 0,
296         bop: -1,
297         eop: -1,
298         // data
299         clearData: function(){
300                 this.pages = [];
301                 this.bop = this.eop = -1;
302                 this.setData([]);
303         },
304         getRowCount: function(){
305                 return this.count;
306         },
307         getColCount: function(){
308                 return this.fields.count();
309         },
310         setRowCount: function(inCount){
311                 this.count = inCount;
312                 this.change();
313         },
314         // paging
315         requestsPending: function(inBoolean){
316         },
317         rowToPage: function(inRowIndex){
318                 return (this.rowsPerPage ? Math.floor(inRowIndex / this.rowsPerPage) : inRowIndex);
319         },
320         pageToRow: function(inPageIndex){
321                 return (this.rowsPerPage ? this.rowsPerPage * inPageIndex : inPageIndex);
322         },
323         requestRows: function(inRowIndex, inCount){
324                 // summary:
325                 //              stub. Fill in to perform actual data row fetching logic. The
326                 //              returning logic must provide the data back to the system via
327                 //              setRow
328         },
329         rowsProvided: function(inRowIndex, inCount){
330                 this.requests--;
331                 if(this.requests == 0){
332                         this.requestsPending(false);
333                 }
334         },
335         requestPage: function(inPageIndex){
336                 var row = this.pageToRow(inPageIndex);
337                 var count = Math.min(this.rowsPerPage, this.count - row);
338                 if(count > 0){
339                         this.requests++;
340                         this.requestsPending(true);
341                         setTimeout(dojo.hitch(this, "requestRows", row, count), 1);
342                         //this.requestRows(row, count);
343                 }
344         },
345         needPage: function(inPageIndex){
346                 if(!this.pages[inPageIndex]){
347                         this.pages[inPageIndex] = true;
348                         this.requestPage(inPageIndex);
349                 }
350         },
351         preparePage: function(inRowIndex, inColIndex){
352                 if(inRowIndex < this.bop || inRowIndex >= this.eop){
353                         var pageIndex = this.rowToPage(inRowIndex);
354                         this.needPage(pageIndex);
355                         this.bop = pageIndex * this.rowsPerPage;
356                         this.eop = this.bop + (this.rowsPerPage || this.count);
357                 }
358         },
359         isRowLoaded: function(inRowIndex){
360                 return Boolean(this.data[inRowIndex]);
361         },
362         // removal
363         removePages: function(inRowIndexes){
364                 for(var i=0, r; ((r=inRowIndexes[i]) != undefined); i++){
365                         this.pages[this.rowToPage(r)] = false;
366                 }
367                 this.bop = this.eop =-1;
368         },
369         remove: function(inRowIndexes){
370                 this.removePages(inRowIndexes);
371                 dojox.grid.data.Table.prototype.remove.apply(this, arguments);
372         },
373         // access
374         getRow: function(inRowIndex){
375                 var row = this.data[inRowIndex];
376                 if(!row){
377                         this.preparePage(inRowIndex);
378                 }
379                 return row;
380         },
381         getDatum: function(inRowIndex, inColIndex){
382                 var row = this.getRow(inRowIndex);
383                 return (row ? row[inColIndex] : this.fields.get(inColIndex).na);
384         },
385         setDatum: function(inDatum, inRowIndex, inColIndex){
386                 var row = this.getRow(inRowIndex);
387                 if(row){
388                         row[inColIndex] = inDatum;
389                         this.datumChange(inDatum, inRowIndex, inColIndex);
390                 }else{
391                         console.debug('[' + this.declaredClass + '] dojox.grid.data.dynamic.set: cannot set data on an non-loaded row');
392                 }
393         },
394         // sort
395         canSort: function(){
396                 return false;
397         }
398 });
399
400 // FIXME: deprecated: (included for backward compatibility only)
401 dojox.grid.data.table = dojox.grid.data.Table;
402 dojox.grid.data.dynamic = dojox.grid.data.Dynamic;
403
404 // we treat dojo.data stores as dynamic stores because no matter how they got
405 // here, they should always fill that contract
406 dojo.declare("dojox.grid.data.DojoData", dojox.grid.data.Dynamic, {
407         //      summary:
408         //              A grid data model for dynamic data retreived from a store which
409         //              implements the dojo.data API set. Retrieves data automatically when
410         //              requested and provides notification when data is received
411         //      description:
412         //              This store subclasses the Dynamic grid data object in order to
413         //              provide paginated data access support, notification and view
414         //              updates for stores which support those features, and simple
415         //              field/column mapping for all dojo.data stores.
416         constructor: function(inFields, inData, args){
417                 this.count = 1;
418                 this._rowIdentities = {};
419                 this._currentlyProcessing = [];
420                 if(args){
421                         dojo.mixin(this, args);
422                 }
423                 if(this.store){
424                         var f = this.store.getFeatures();
425                         this._canNotify = f['dojo.data.api.Notification'];
426                         this._canWrite = f['dojo.data.api.Write'];
427                         this._canIdentify = f['dojo.data.api.Identity'];
428                         if(this._canNotify){
429                                 dojo.connect(this.store, "onSet", this, "_storeDatumChange");
430                                 dojo.connect(this.store, "onDelete", this, "_storeDatumDelete");
431                                 dojo.connect(this.store, "onNew", this, "_storeDatumNew");
432                         }
433                         if(this._canWrite) {
434                                 dojo.connect(this.store, "revert", this, "refresh");
435                         }
436                 }
437         },
438         markupFactory: function(args, node){
439                 return new dojox.grid.data.DojoData(null, null, args);
440         },
441         query: { name: "*" }, // default, stupid query
442         store: null,
443         _currentlyProcessing: null,
444         _canNotify: false,
445         _canWrite: false,
446         _canIdentify: false,
447         _rowIdentities: {},
448         clientSort: false,
449         sortFields: null,
450         queryOptions: null,
451
452         // data
453         setData: function(inData){
454                 this.store = inData;
455                 this.data = [];
456                 this.allChange();
457         },
458         setRowCount: function(inCount){
459                 //console.debug("inCount:", inCount);
460                 this.count = inCount;
461                 this.allChange();
462         },
463         beginReturn: function(inCount){
464                 if(this.count != inCount){
465                         // this.setRowCount(0);
466                         // this.clear();
467                         // console.debug(this.count, inCount);
468                         this.setRowCount(inCount);
469                 }
470         },
471         _setupFields: function(dataItem){
472                 // abort if we already have setup fields
473                 if(this.fields._nameMaps){
474                         return;
475                 }
476                 // set up field/index mappings
477                 var m = {};
478                 //console.debug("setting up fields", m);
479                 var fields = dojo.map(this.store.getAttributes(dataItem),
480                         function(item, idx){ 
481                                 m[item] = idx;
482                                 m[idx+".idx"] = item;
483                                 // name == display name, key = property name
484                                 return { name: item, key: item };
485                         },
486                         this
487                 );
488                 this.fields._nameMaps = m;
489                 // console.debug("new fields:", fields);
490                 this.fields.set(fields);
491                 this.notify("FieldsChange");
492         },
493         _getRowFromItem: function(item){
494                 // gets us the row object (and row index) of an item
495         },
496         _createRow: function(item){
497                 var row = {}; 
498                 row.__dojo_data_item = item;
499                 dojo.forEach(this.fields.values, function(a){
500                         value = this.store.getValue(item, a.name);
501                         row[a.name] = (value === undefined || value === null)?"":value;
502                 }, this);
503                 return row;
504         },
505         processRows: function(items, request){
506                 // console.debug(arguments);
507                 if(!items || items.length == 0){ return; }
508                 this._setupFields(items[0]);
509                 dojo.forEach(items, function(item, idx){
510                         var row = this._createRow(item);
511                         this._setRowId(item, request.start, idx);
512                         this.setRow(row, request.start+idx);
513                 }, this);
514                 // FIXME: 
515                 //      Q: scott, steve, how the hell do we actually get this to update
516                 //              the visible UI for these rows?
517                 //      A: the goal is that Grid automatically updates to reflect changes
518                 //              in model. In this case, setRow -> rowChanged -> (observed by) Grid -> modelRowChange -> updateRow
519         },
520         // request data 
521         requestRows: function(inRowIndex, inCount){
522                 var row  = inRowIndex || 0;
523                 var params = { 
524                         start: row,
525                         count: this.rowsPerPage,
526                         query: this.query,
527                         sort: this.sortFields,
528                         queryOptions: this.queryOptions,
529                         onBegin: dojo.hitch(this, "beginReturn"),
530                         onComplete: dojo.hitch(this, "processRows"), // add to deferred?
531                         onError: dojo.hitch(this, "processError")
532                 };
533                 this.store.fetch(params);
534         },
535         getDatum: function(inRowIndex, inColIndex){
536                 //console.debug("getDatum", inRowIndex, inColIndex);
537                 var row = this.getRow(inRowIndex);
538                 var field = this.fields.values[inColIndex];
539                 return row && field ? row[field.name] : field ? field.na : '?';
540                 //var idx = row && this.fields._nameMaps[inColIndex+".idx"];
541                 //return (row ? row[idx] : this.fields.get(inColIndex).na);
542         },
543         setDatum: function(inDatum, inRowIndex, inColIndex){
544                 var n = this.fields._nameMaps[inColIndex+".idx"];
545                 // console.debug("setDatum:", "n:"+n, inDatum, inRowIndex, inColIndex);
546                 if(n){
547                         this.data[inRowIndex][n] = inDatum;
548                         this.datumChange(inDatum, inRowIndex, inColIndex);
549                 }
550         },
551         // modification, update and store eventing
552         copyRow: function(inRowIndex){
553                 var row = {};
554                 var backstop = {};
555                 var src = this.getRow(inRowIndex);
556                 for(var x in src){
557                         if(src[x] != backstop[x]){
558                                 row[x] = src[x];
559                         }
560                 }
561                 return row;
562         },
563         _attrCompare: function(cache, data){
564                 dojo.forEach(this.fields.values, function(a){
565                         if(cache[a.name] != data[a.name]){ return false; }
566                 }, this);
567                 return true;
568         },
569         endModifyRow: function(inRowIndex){
570                 var cache = this.cache[inRowIndex];
571                 if(cache){
572                         var data = this.getRow(inRowIndex);
573                         if(!this._attrCompare(cache, data)){
574                                 this.update(cache, data, inRowIndex);
575                         }
576                         delete this.cache[inRowIndex];
577                 }
578         },
579         cancelModifyRow: function(inRowIndex){
580                 // console.debug("cancelModifyRow", arguments);
581                 var cache = this.cache[inRowIndex];
582                 if(cache){
583                         this.setRow(cache, inRowIndex);
584                         delete this.cache[inRowIndex];
585                 }
586         },
587         _setRowId: function(item, offset, idx){
588                 // FIXME: where else do we need to keep this in sync?
589                 //Handle stores that implement identity and try to handle those that do not.
590                 if (this._canIdentify) {
591                         this._rowIdentities[this.store.getIdentity(item)] = {rowId: offset+idx, item: item};
592                 }else{
593                         var identity = dojo.toJson(this.query) + ":start:" + offset + ":idx:" + idx + ":sort:" + dojo.toJson(this.sortFields);
594                         this._rowIdentities[identity] = {rowId: offset+idx, item: item};
595                 }
596         },
597         _getRowId: function(item, isNotItem){
598                 //      summary:
599                 //              Function determine the row index for a particular item
600                 //      item:
601                 //              The store item to examine to determine row index.
602                 //      isNotItem:
603                 //              Boolean flag to indicate if the item passed is a store item or not.
604                 var rowId = null;
605                 //Handle identity and nonidentity capable stores.
606                 if(this._canIdentify && !isNotItem){
607                         rowId = this._rowIdentities[this.store.getIdentity(item)].rowId;
608                 }else{
609                         //Not efficient, but without identity support, 
610                         //not a better way to do it.  Basically, do our best to locate it
611                         //This may or may not work, but best we can do here.
612                         var id;
613                         for(id in this._rowIdentities){
614                                 if(this._rowIdentities[id].item === item){
615                                         rowId = this._rowIdentities[id].rowId;
616                                         break;
617                                 }
618                         }
619                 }
620                 return rowId;
621         },
622         _storeDatumChange: function(item, attr, oldVal, newVal){
623                 // the store has changed some data under us, need to update the display
624                 var rowId = this._getRowId(item);
625                 var row = this.getRow(rowId);
626                 if(row){
627                         row[attr] = newVal;
628                         var colId = this.fields._nameMaps[attr];
629                         this.notify("DatumChange", [ newVal, rowId, colId ]);
630                 }
631         },
632         _storeDatumDelete: function(item){
633                 if(dojo.indexOf(this._currentlyProcessing, item) != -1)
634                         return;
635                 // the store has deleted some item under us, need to remove that item from
636                 // the view if possible.  It may be the deleted item isn't even in the grid.
637                 var rowId = this._getRowId(item, true);
638                 if(rowId != null){
639                         this._removeItems([rowId]);
640                 }
641         },
642         _storeDatumNew: function(item){
643                 if(this._disableNew){
644                         return;
645                 }
646                 // the store has added some item under us, need to add it to the view.
647                 this._insertItem(item, this.data.length);
648         },
649         insert: function(item, index){
650                 // Push the given item back to the store
651                 this._disableNew = true;
652                 var i = this.store.newItem(item);
653                 this._disableNew = false;
654                 this._insertItem(i, index);
655         },
656         _insertItem: function(storeItem, index){
657                 // Set up our fields if we haven't already 
658                 if(!this.fields._nameMaps){
659                         this._setupFields(storeItem);
660                 }
661                 var row = this._createRow(storeItem);
662                 for(var i in this._rowIdentities){ //increment all the remaining row ids up one
663                         var rowIdentity = this._rowIdentities[i];
664                         if(rowIdentity.rowId >= index){
665                                 rowIdentity.rowId++;
666                         }
667                 }
668                 this._setRowId(storeItem, 0, index);
669                 dojox.grid.data.Dynamic.prototype.insert.apply(this, [row, index]);
670         },
671         datumChange: function(value, rowIdx, colIdx){
672                 if(this._canWrite){
673                         // we're chaning some data, which means we need to write back
674                         var row = this.getRow(rowIdx);
675                         var field = this.fields._nameMaps[colIdx+".idx"];
676                         this.store.setValue(row.__dojo_data_item, field, value);
677                         // we don't need to call DatumChange, an eventing store will tell
678                         // us about the row change events
679                 }else{
680                         // we can't write back, so just go ahead and change our local copy
681                         // of the data
682                         this.notify("DatumChange", arguments);
683                 }
684         },
685         insertion: function(/* index */){
686                 console.debug("Insertion", arguments);
687                 this.notify("Insertion", arguments);
688                 this.notify("Change", arguments);
689         },
690         removal: function(/* keys */){
691                 console.debug("Removal", arguments);
692                 this.notify("Removal", arguments);
693                 this.notify("Change", arguments);
694         },
695         remove: function(inRowIndexes){
696                 //      summary:
697                 //              Function to remove a set of items from the store based on the row index.
698                 //      inRowIndexes:
699                 //              An array of row indexes from the grid to remove from the store.
700                 /* Call delete on the store */ 
701                 for(var i=inRowIndexes.length-1; i>=0; i--){
702                         // Need to find the item, then remove each from the data store
703                         var item = this.data[inRowIndexes[i]].__dojo_data_item;
704                         this._currentlyProcessing.push(item);
705                         this.store.deleteItem(item);
706                 }
707                 /* Remove from internal data structure and the view */
708                 this._removeItems(inRowIndexes);
709                 this._currentlyProcessing = [];
710         },
711         _removeItems: function(inRowIndexes /*array*/){
712                 //      summary:
713                 //              Function to remove a set of items from the store based on the row index.
714                 //      inRowIndexes:
715                 //              An array of row indexes from the grid to remove from the store.
716                 dojox.grid.data.Dynamic.prototype.remove.apply(this, arguments);
717                 // Rebuild _rowIdentities
718                 this._rowIdentities = {};
719                 for (var i = 0; i < this.data.length; i++){
720                         this._setRowId(this.data[i].__dojo_data_item, 0, i);
721                 }
722         },
723         canSort: function(){
724                 // Q: Return true and re-issue the queries?
725                 // A: Return true only. Re-issue the query in 'sort'.
726                 // Note, above are original comments :)
727                 return true;
728         },
729         sort: function(colIndex){
730                 var col = Math.abs(colIndex) - 1;
731                 this.sortFields = [{'attribute': this.fields.values[col].name, 'descending': (colIndex>0)}];
732                 
733                 // Since we're relying on the data store to sort, we have to refresh our data.
734                 this.refresh();
735         },
736         refresh: function(){
737                 //      summary:
738                 //              Function to cause the model to re-query the store and rebuild the current viewport.
739                 this.clearData(true);
740                 this.requestRows();
741         },
742         clearData: function(/* boolean */ keepStore){
743                 this._rowIdentities = {};
744                 this.pages = [];
745                 this.bop = this.eop = -1;
746                 this.count = 0;
747                 this.setData((keepStore?this.store:[]));
748         },
749         processError: function(error, request){
750                 //      summary:
751                 //              Hook function to trap error messages from the store and emit them.  
752                 //              Intended for connecting to and handling the error object or at least reporting it.
753                 //
754                 //      error:
755                 //              The error object returned by the store when a problem occurred.
756                 //      request:
757                 //              The request object that caused the error.
758                 console.log(error);
759         }
760 });
761
762 }