]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/dojo/openils/widget/AutoGrid.js
remove debug log
[working/Evergreen.git] / Open-ILS / web / js / dojo / openils / widget / AutoGrid.js
1 if(!dojo._hasResource['openils.widget.AutoGrid']) {
2     dojo.provide('openils.widget.AutoGrid');
3     dojo.require('dojox.grid.DataGrid');
4     dojo.require('openils.widget.AutoWidget');
5     dojo.require('openils.widget.AutoFieldWidget');
6     dojo.require('openils.widget.EditPane');
7     dojo.require('openils.widget.EditDialog');
8     dojo.require('openils.Util');
9
10     dojo.declare(
11         'openils.widget.AutoGrid',
12         [dojox.grid.DataGrid, openils.widget.AutoWidget],
13         {
14
15             /* if true, pop up an edit dialog when user hits Enter on a give row */
16             editOnEnter : false, 
17             defaultCellWidth : null,
18             editStyle : 'dialog',
19             suppressFields : null,
20             hideSelector : false,
21             selectorWidth : '1.5',
22
23             /* by default, don't show auto-generated (sequence) fields */
24             showSequenceFields : false, 
25
26             startup : function() {
27                 this.selectionMode = 'single';
28                 this.sequence = openils.widget.AutoGrid.sequence++;
29                 openils.widget.AutoGrid.gridCache[this.sequence] = this;
30                 this.inherited(arguments);
31                 this.initAutoEnv();
32                 this.attr('structure', this._compileStructure());
33                 this.setStore(this.buildAutoStore());
34                 this.overrideEditWidgets = {};
35                 this.overrideEditWidgetClass = {};
36                 if(this.editOnEnter) 
37                     this._applyEditOnEnter();
38                 else if(this.singleEditStyle) 
39                     this._applySingleEditStyle();
40
41                 if(!this.hideSelector) {
42                     var header = this.layout.cells[0].view.getHeaderCellNode(0);
43                     var self = this;
44                     header.onclick = function() { self.toggleSelectAll(); }
45                 }
46             },
47
48             /* Don't allow sorting on the selector column */
49             canSort : function(rowIdx) {
50                 if(rowIdx == 1 && !this.hideSelector)
51                     return false;
52                 return true;
53             },
54
55             _compileStructure : function() {
56                 var existing = (this.structure && this.structure[0].cells[0]) ? 
57                     this.structure[0].cells[0] : [];
58                 var fields = [];
59
60                 var self = this;
61                 function pushEntry(entry) {
62                     if(self.suppressFields) {
63                         if(dojo.indexOf(self.suppressFields, entry.field) != -1)
64                             return;
65                     }
66                     if(!entry.get) 
67                         entry.get = openils.widget.AutoGrid.defaultGetter
68                     if(!entry.width && self.defaultCellWidth)
69                         entry.width = self.defaultCellWidth;
70                     fields.push(entry);
71                 }
72
73                 if(!this.hideSelector) {
74                     // insert the selector column
75                     pushEntry({
76                         field : '+selector',
77                         formatter : function(rowIdx) { return self._formatRowSelectInput(rowIdx); },
78                         get : function(rowIdx, item) { if(item) return rowIdx; },
79                         width : this.selectorWidth,
80                         name : '&#x2713'
81                     });
82                 }
83
84
85                 if(!this.fieldOrder) {
86                     /* no order defined, start with any explicit grid fields */
87                     for(var e in existing) {
88                         var entry = existing[e];
89                         var field = this.fmIDL.fields.filter(
90                             function(i){return (i.name == entry.field)})[0];
91                         if(field) entry.name = entry.name || field.label;
92                         pushEntry(entry);
93                     }
94                 }
95
96                 for(var f in this.sortedFieldList) {
97                     var field = this.sortedFieldList[f];
98                     if(!field || field.virtual) continue;
99                     
100                     // field was already added above
101                     if(fields.filter(function(i){return (i.field == field.name)})[0]) 
102                         continue;
103
104                     var entry = existing.filter(function(i){return (i.field == field.name)})[0];
105                     if(entry) {
106                         entry.name = field.label;
107                     } else {
108                         // unless specifically requested, hide sequence fields
109                         if(!this.showSequenceFields && field.name == this.fmIDL.pkey && this.fmIDL.pkey_sequence)
110                             continue; 
111
112                         entry = {field:field.name, name:field.label};
113                     }
114                     pushEntry(entry);
115                 }
116
117                 if(this.fieldOrder) {
118                     /* append any explicit non-IDL grid fields to the end */
119                     for(var e in existing) {
120                         var entry = existing[e];
121                         var field = fields.filter(
122                             function(i){return (i.field == entry.field)})[0];
123                         if(field) continue; // don't duplicate
124                         pushEntry(entry);
125                     }
126                 }
127
128                 return [{cells: [fields]}];
129             },
130
131             toggleSelectAll : function() {
132                 var selected = this.getSelectedRows();
133                 for(var i = 0; i < this.rowCount; i++) {
134                     if(selected[0])
135                         this.deSelectRow(i);
136                     else
137                         this.selectRow(i);
138                 }
139             },
140
141             getSelectedRows : function() {
142                 var rows = []; 
143                 dojo.forEach(
144                     dojo.query('[name=autogrid.selector]', this.domNode),
145                     function(input) {
146                         if(input.checked)
147                             rows.push(input.getAttribute('row'));
148                     }
149                 );
150                 return rows;
151             },
152
153             getFirstSelectedRow : function() {
154                 return this.getSelectedRows()[0];
155             },
156
157             getSelectedItems : function() {
158                 var items = [];
159                 var self = this;
160                 dojo.forEach(this.getSelectedRows(), function(idx) { items.push(self.getItem(idx)); });
161                 return items;
162             },
163
164             selectRow : function(rowIdx) {
165                 var inputs = dojo.query('[name=autogrid.selector]', this.domNode);
166                 for(var i = 0; i < inputs.length; i++) {
167                     if(inputs[i].getAttribute('row') == rowIdx) {
168                         inputs[i].checked = true;
169                         break;
170                     }
171                 }
172             },
173
174             deSelectRow : function(rowIdx) {
175                 var inputs = dojo.query('[name=autogrid.selector]', this.domNode);
176                 for(var i = 0; i < inputs.length; i++) {
177                     if(inputs[i].getAttribute('row') == rowIdx) {
178                         inputs[i].checked = false;
179                         break;
180                     }
181                 }
182             },
183
184             deleteSelected : function() {
185                 var items = this.getSelectedItems();
186                 var total = items.length;
187                 var self = this;
188                 dojo.require('openils.PermaCrud');
189                 var pcrud = new openils.PermaCrud();
190                 dojo.forEach(items,
191                     function(item) {
192                         var fmObject = new fieldmapper[self.fmClass]().fromStoreItem(item);
193                         pcrud['delete'](fmObject, {oncomplete : function(r) { self.store.deleteItem(item) }});
194                     }
195                 );
196             },
197
198             _formatRowSelectInput : function(rowIdx) {
199                 if(rowIdx === null || rowIdx === undefined) return '';
200                 return "<input type='checkbox' name='autogrid.selector' row='" + rowIdx + "'/>";
201             },
202
203             _applySingleEditStyle : function() {
204                 this.onMouseOverRow = function(e) {};
205                 this.onMouseOutRow = function(e) {};
206                 this.onCellFocus = function(cell, rowIndex) { 
207                     this.selection.deselectAll();
208                     this.selection.select(this.focus.rowIndex);
209                 };
210             },
211
212             /* capture keydown and launch edit dialog on enter */
213             _applyEditOnEnter : function() {
214                 this._applySingleEditStyle();
215
216                 dojo.connect(this, 'onRowDblClick',
217                     function(e) {
218                         if(this.editStyle == 'pane')
219                             this._drawEditPane(this.selection.getFirstSelected(), this.focus.rowIndex);
220                         else
221                             this._drawEditDialog(this.selection.getFirstSelected(), this.focus.rowIndex);
222                     }
223                 );
224
225                 dojo.connect(this, 'onKeyDown',
226                     function(e) {
227                         if(e.keyCode == dojo.keys.ENTER) {
228                             this.selection.deselectAll();
229                             this.selection.select(this.focus.rowIndex);
230                             if(this.editStyle == 'pane')
231                                 this._drawEditPane(this.selection.getFirstSelected(), this.focus.rowIndex);
232                             else
233                                 this._drawEditDialog(this.selection.getFirstSelected(), this.focus.rowIndex);
234                         }
235                     }
236                 );
237             },
238
239             _makeEditPane : function(storeItem, rowIndex, onPostSubmit, onCancel) {
240                 var grid = this;
241                 var fmObject = new fieldmapper[this.fmClass]().fromStoreItem(storeItem);
242                 var idents = grid.store.getIdentityAttributes();
243
244                 var pane = new openils.widget.EditPane({
245                     fmObject:fmObject,
246                     overrideWidgets : this.overrideEditWidgets,
247                     overrideWidgetClass : this.overrideEditWidgetClass,
248                     disableWidgetTest : this.disableWidgetTest,
249                     onPostSubmit : function() {
250                         for(var i in fmObject._fields) {
251                             var field = fmObject._fields[i];
252                             if(idents.filter(function(j){return (j == field)})[0])
253                                 continue; // don't try to edit an identifier field
254                             grid.store.setValue(storeItem, field, fmObject[field]());
255                         }
256                         if(self.onPostUpdate)
257                             self.onPostUpdate(storeItem, rowIndex);
258                         setTimeout(
259                             function(){
260                                 try { 
261                                     grid.views.views[0].getCellNode(rowIndex, 0).focus(); 
262                                 } catch (E) {}
263                             },200
264                         );
265                         if(onPostSubmit) onPostSubmit();
266                     },
267                     onCancel : function() {
268                         setTimeout(function(){
269                             grid.views.views[0].getCellNode(rowIndex, 0).focus();},200);
270                         if(onCancel) onCancel();
271                     }
272                 });
273
274                 pane.fieldOrder = this.fieldOrder;
275                 pane.mode = 'update';
276                 return pane;
277             },
278
279             _makeCreatePane : function(onPostSubmit, onCancel) {
280                 var grid = this;
281                 var pane = new openils.widget.EditPane({
282                     fmClass : this.fmClass,
283                     overrideWidgets : this.overrideEditWidgets,
284                     overrideWidgetClass : this.overrideEditWidgetClass,
285                     disableWidgetTest : this.disableWidgetTest,
286                     onPostSubmit : function(r) {
287                         var fmObject = openils.Util.readResponse(r);
288                         if(fmObject) 
289                             grid.store.newItem(fmObject.toStoreItem());
290                         if(grid.onPostCreate)
291                             grid.onPostCreate(fmObject);
292                         setTimeout(function(){
293                             try {
294                                 grid.selection.select(grid.rowCount-1);
295                                 grid.views.views[0].getCellNode(grid.rowCount-1, 1).focus();
296                             } catch (E) {}
297                         },200);
298                         if(onPostSubmit)
299                             onPostSubmit();
300                     },
301                     onCancel : function() {
302                         if(onCancel) onCancel();
303                     }
304                 });
305                 pane.fieldOrder = this.fieldOrder;
306                 pane.mode = 'create';
307                 return pane;
308             },
309
310             // .startup() is called within
311             _makeClonePane : function(storeItem, rowIndex, onPostSubmit, onCancel) {
312                 var clonePane = this._makeCreatePane(onPostSubmit, onCancel);
313                 var origPane = this._makeEditPane(storeItem, rowIndex);
314                 clonePane.startup();
315                 origPane.startup();
316                 dojo.forEach(origPane.fieldList,
317                     function(field) {
318                         if(field.widget.widget.attr('disabled')) return;
319                         var w = clonePane.fieldList.filter(
320                             function(i) { return (i.name == field.name) })[0];
321                         w.widget.baseWidgetValue(field.widget.widgetValue); // sync widgets
322                         w.widget.onload = function(){w.widget.baseWidgetValue(field.widget.widgetValue)}; // async widgets
323                     }
324                 );
325                 origPane.destroy();
326                 return clonePane;
327             },
328
329
330             _drawEditDialog : function(storeItem, rowIndex) {
331                 var self = this;
332                 var done = function() { self.hideDialog(); };
333                 var pane = this._makeEditPane(storeItem, rowIndex, done, done);
334                 this.editDialog = new openils.widget.EditDialog({editPane:pane});
335                 this.editDialog.startup();
336                 this.editDialog.show();
337             },
338
339             showCreateDialog : function() {
340                 var self = this;
341                 var done = function() { self.hideDialog(); };
342                 var pane = this._makeCreatePane(done, done);
343                 this.editDialog = new openils.widget.EditDialog({editPane:pane});
344                 this.editDialog.startup();
345                 this.editDialog.show();
346             },
347
348             _drawEditPane : function(storeItem, rowIndex) {
349                 var self = this;
350                 var done = function() { self.hidePane(); };
351                 dojo.style(this.domNode, 'display', 'none');
352                 this.editPane = this._makeEditPane(storeItem, rowIndex, done, done);
353                 this.editPane.startup();
354                 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
355             },
356
357             showClonePane : function() {
358                 var self = this;
359                 var done = function() { self.hidePane(); };
360                 var row = this.getFirstSelectedRow();
361                 if(!row) return;
362                 dojo.style(this.domNode, 'display', 'none');
363                 this.editPane = this._makeClonePane(this.getItem(row), row, done, done);
364                 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
365             },
366
367             showCreatePane : function() {
368                 var self = this;
369                 var done = function() { self.hidePane(); };
370                 dojo.style(this.domNode, 'display', 'none');
371                 this.editPane = this._makeCreatePane(done, done);
372                 this.editPane.startup();
373                 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
374             },
375
376             hideDialog : function() {
377                 this.editDialog.hide(); 
378                 this.editDialog.destroy(); 
379                 delete this.editDialog;
380                 this.update();
381             },
382
383             hidePane : function() {
384                 this.domNode.parentNode.removeChild(this.editPane.domNode);
385                 this.editPane.destroy();
386                 delete this.editPane;
387                 dojo.style(this.domNode, 'display', 'block');
388                 this.update();
389             },
390             
391             resetStore : function() {
392                 this.setStore(this.buildAutoStore());
393             },
394
395             loadAll : function(opts, search) {
396                 dojo.require('openils.PermaCrud');
397                 if(!opts) opts = {};
398                 var self = this;
399                 opts = dojo.mixin(opts, {
400                     async : true,
401                     streaming : true,
402                     onresponse : function(r) {
403                         var item = openils.Util.readResponse(r);
404                         self.store.newItem(item.toStoreItem());
405                     }
406                 });
407                 if(search)
408                     new openils.PermaCrud().search(this.fmClass, search, opts);
409                 else
410                     new openils.PermaCrud().retrieveAll(this.fmClass, opts);
411             }
412         } 
413     );
414
415     // static ID generater seed
416     openils.widget.AutoGrid.sequence = 0;
417     openils.widget.AutoGrid.gridCache = {};
418
419     openils.widget.AutoGrid.markupFactory = dojox.grid.DataGrid.markupFactory;
420
421     openils.widget.AutoGrid.defaultGetter = function(rowIndex, item) {
422         if(!item) return '';
423         var val = this.grid.store.getValue(item, this.field);
424         var autoWidget = new openils.widget.AutoFieldWidget({
425             fmClass: this.grid.fmClass,
426             fmField: this.field,
427             widgetValue : val,
428             readOnly : true,
429             forceSync : true
430         });
431         //autoWidget.build();
432         return autoWidget.getDisplayString();
433     }
434 }
435