1 if(!dojo._hasResource['openils.widget.AutoGrid']) {
2 dojo.provide('openils.widget.AutoGrid');
3 dojo.require('dojox.grid.DataGrid');
4 dojo.require('dijit.layout.ContentPane');
5 dojo.require('openils.widget.AutoWidget');
6 dojo.require('openils.widget.AutoFieldWidget');
7 dojo.require('openils.widget.EditPane');
8 dojo.require('openils.widget.EditDialog');
9 dojo.require('openils.widget.GridColumnPicker');
10 dojo.require('openils.Util');
13 'openils.widget.AutoGrid',
14 [dojox.grid.DataGrid, openils.widget.AutoWidget],
17 /* if true, pop up an edit dialog when user hits Enter on a give row */
19 defaultCellWidth : null,
21 suppressFields : null,
23 selectorWidth : '1.5',
24 showColumnPicker : false,
25 columnPickerPrefix : null,
28 showPaginator : false,
30 /* by default, don't show auto-generated (sequence) fields */
31 showSequenceFields : false,
33 startup : function() {
34 this.selectionMode = 'single';
35 this.sequence = openils.widget.AutoGrid.sequence++;
36 openils.widget.AutoGrid.gridCache[this.sequence] = this;
37 this.inherited(arguments);
39 this.attr('structure', this._compileStructure());
40 this.setStore(this.buildAutoStore());
41 this.cachedQueryOpts = {};
43 if(this.showColumnPicker) {
44 if(!this.columnPickerPrefix) {
45 console.error("No columnPickerPrefix defined");
47 var picker = new openils.widget.GridColumnPicker(
48 openils.User.authtoken, this.columnPickerPrefix, this);
49 if(openils.User.authtoken) {
52 openils.Util.addOnLoad(function() { picker.load() });
57 this.overrideEditWidgets = {};
58 this.overrideEditWidgetClass = {};
61 this._applyEditOnEnter();
62 else if(this.singleEditStyle)
63 this._applySingleEditStyle();
65 if(!this.hideSelector) {
66 dojo.connect(this, 'onHeaderCellClick',
69 this.toggleSelectAll();
74 if(this.showPaginator) {
76 this.paginator = new dijit.layout.ContentPane();
79 var back = dojo.create('a', {
81 style : 'padding-right:6px;',
82 href : 'javascript:void(0);',
83 onclick : function() {
85 self.cachedQueryOpts.offset = self.displayOffset -= self.displayLimit;
89 self.loadAll(self.cachedQueryOpts, self.cachedQuerySearch);
93 var forw = dojo.create('a', {
95 style : 'padding-right:6px;',
96 href : 'javascript:void(0);',
97 onclick : function() {
99 self.cachedQueryOpts.offset = self.displayOffset += self.displayLimit;
103 self.loadAll(self.cachedQueryOpts, self.cachedQuerySearch);
107 dojo.place(this.paginator.domNode, this.domNode, 'before');
108 dojo.place(back, this.paginator.domNode);
109 dojo.place(forw, this.paginator.domNode);
110 this.loadProgressIndicator = dojo.create('img', {
111 src:'/opac/images/progressbar_green.gif',
112 style:'height:16px;width:16px;'
114 dojo.place(this.loadProgressIndicator, this.paginator.domNode);
118 hideLoadProgressIndicator : function() {
119 dojo.style(this.loadProgressIndicator, 'visibility', 'hidden');
122 showLoadProgressIndicator : function() {
123 dojo.style(this.loadProgressIndicator, 'visibility', 'visible');
126 /* Don't allow sorting on the selector column */
127 canSort : function(rowIdx) {
128 if(rowIdx == 1 && !this.hideSelector)
133 _compileStructure : function() {
134 var existing = (this.structure && this.structure[0].cells[0]) ?
135 this.structure[0].cells[0] : [];
139 function pushEntry(entry) {
140 if(self.suppressFields) {
141 if(dojo.indexOf(self.suppressFields, entry.field) != -1)
145 entry.get = openils.widget.AutoGrid.defaultGetter
146 if(!entry.width && self.defaultCellWidth)
147 entry.width = self.defaultCellWidth;
151 if(!this.hideSelector) {
152 // insert the selector column
155 formatter : function(rowIdx) { return self._formatRowSelectInput(rowIdx); },
156 get : function(rowIdx, item) { if(item) return rowIdx; },
157 width : this.selectorWidth,
164 if(!this.fieldOrder) {
165 /* no order defined, start with any explicit grid fields */
166 for(var e in existing) {
167 var entry = existing[e];
168 var field = this.fmIDL.fields.filter(
169 function(i){return (i.name == entry.field)})[0];
170 if(field) entry.name = entry.name || field.label;
175 for(var f in this.sortedFieldList) {
176 var field = this.sortedFieldList[f];
177 if(!field || field.virtual) continue;
179 // field was already added above
180 if(fields.filter(function(i){return (i.field == field.name)})[0])
183 var entry = existing.filter(function(i){return (i.field == field.name)})[0];
185 entry.name = field.label;
187 // unless specifically requested, hide sequence fields
188 if(!this.showSequenceFields && field.name == this.fmIDL.pkey && this.fmIDL.pkey_sequence)
191 entry = {field:field.name, name:field.label};
196 if(this.fieldOrder) {
197 /* append any explicit non-IDL grid fields to the end */
198 for(var e in existing) {
199 var entry = existing[e];
200 var field = fields.filter(
201 function(i){return (i.field == entry.field)})[0];
202 if(field) continue; // don't duplicate
207 return [{cells: [fields]}];
210 toggleSelectAll : function() {
211 var selected = this.getSelectedRows();
212 for(var i = 0; i < this.rowCount; i++) {
220 getSelectedRows : function() {
223 dojo.query('[name=autogrid.selector]', this.domNode),
226 rows.push(input.getAttribute('row'));
232 getFirstSelectedRow : function() {
233 return this.getSelectedRows()[0];
236 getSelectedItems : function() {
239 dojo.forEach(this.getSelectedRows(), function(idx) { items.push(self.getItem(idx)); });
243 selectRow : function(rowIdx) {
244 var inputs = dojo.query('[name=autogrid.selector]', this.domNode);
245 for(var i = 0; i < inputs.length; i++) {
246 if(inputs[i].getAttribute('row') == rowIdx) {
247 if(!inputs[i].disabled)
248 inputs[i].checked = true;
254 deSelectRow : function(rowIdx) {
255 var inputs = dojo.query('[name=autogrid.selector]', this.domNode);
256 for(var i = 0; i < inputs.length; i++) {
257 if(inputs[i].getAttribute('row') == rowIdx) {
258 inputs[i].checked = false;
264 getAllObjects : function() {
268 onComplete : function(list) {
271 objs.push(new fieldmapper[self.fmClass]().fromStoreItem(item));
279 deleteSelected : function() {
280 var items = this.getSelectedItems();
281 var total = items.length;
283 dojo.require('openils.PermaCrud');
284 var pcrud = new openils.PermaCrud();
287 var fmObject = new fieldmapper[self.fmClass]().fromStoreItem(item);
288 pcrud['delete'](fmObject, {oncomplete : function(r) { self.store.deleteItem(item) }});
293 _formatRowSelectInput : function(rowIdx) {
294 if(rowIdx === null || rowIdx === undefined) return '';
295 var s = "<input type='checkbox' name='autogrid.selector' row='" + rowIdx + "'";
296 if(this.disableSelectorForRow && this.disableSelectorForRow(rowIdx))
297 s += " disabled='disabled'";
301 _applySingleEditStyle : function() {
302 this.onMouseOverRow = function(e) {};
303 this.onMouseOutRow = function(e) {};
304 this.onCellFocus = function(cell, rowIndex) {
305 this.selection.deselectAll();
306 this.selection.select(this.focus.rowIndex);
310 /* capture keydown and launch edit dialog on enter */
311 _applyEditOnEnter : function() {
312 this._applySingleEditStyle();
314 dojo.connect(this, 'onRowDblClick',
316 if(this.editStyle == 'pane')
317 this._drawEditPane(this.selection.getFirstSelected(), this.focus.rowIndex);
319 this._drawEditDialog(this.selection.getFirstSelected(), this.focus.rowIndex);
323 dojo.connect(this, 'onKeyDown',
325 if(e.keyCode == dojo.keys.ENTER) {
326 this.selection.deselectAll();
327 this.selection.select(this.focus.rowIndex);
328 if(this.editStyle == 'pane')
329 this._drawEditPane(this.selection.getFirstSelected(), this.focus.rowIndex);
331 this._drawEditDialog(this.selection.getFirstSelected(), this.focus.rowIndex);
337 _makeEditPane : function(storeItem, rowIndex, onPostSubmit, onCancel) {
339 var fmObject = new fieldmapper[this.fmClass]().fromStoreItem(storeItem);
340 var idents = grid.store.getIdentityAttributes();
342 var pane = new openils.widget.EditPane({
344 overrideWidgets : this.overrideEditWidgets,
345 overrideWidgetClass : this.overrideEditWidgetClass,
346 disableWidgetTest : this.disableWidgetTest,
347 onPostSubmit : function() {
348 for(var i in fmObject._fields) {
349 var field = fmObject._fields[i];
350 if(idents.filter(function(j){return (j == field)})[0])
351 continue; // don't try to edit an identifier field
352 grid.store.setValue(storeItem, field, fmObject[field]());
354 if(self.onPostUpdate)
355 self.onPostUpdate(storeItem, rowIndex);
359 grid.views.views[0].getCellNode(rowIndex, 0).focus();
363 if(onPostSubmit) onPostSubmit();
365 onCancel : function() {
366 setTimeout(function(){
367 grid.views.views[0].getCellNode(rowIndex, 0).focus();},200);
368 if(onCancel) onCancel();
372 pane.fieldOrder = this.fieldOrder;
373 pane.mode = 'update';
377 _makeCreatePane : function(onPostSubmit, onCancel) {
379 var pane = new openils.widget.EditPane({
380 fmClass : this.fmClass,
381 overrideWidgets : this.overrideEditWidgets,
382 overrideWidgetClass : this.overrideEditWidgetClass,
383 disableWidgetTest : this.disableWidgetTest,
384 onPostSubmit : function(r) {
385 var fmObject = openils.Util.readResponse(r);
386 if(grid.onPostCreate)
387 grid.onPostCreate(fmObject);
389 grid.store.newItem(fmObject.toStoreItem());
390 setTimeout(function(){
392 grid.selection.select(grid.rowCount-1);
393 grid.views.views[0].getCellNode(grid.rowCount-1, 1).focus();
399 onCancel : function() {
400 if(onCancel) onCancel();
403 pane.fieldOrder = this.fieldOrder;
404 pane.mode = 'create';
408 // .startup() is called within
409 _makeClonePane : function(storeItem, rowIndex, onPostSubmit, onCancel) {
410 var clonePane = this._makeCreatePane(onPostSubmit, onCancel);
411 var origPane = this._makeEditPane(storeItem, rowIndex);
414 dojo.forEach(origPane.fieldList,
416 if(field.widget.widget.attr('disabled')) return;
417 var w = clonePane.fieldList.filter(
418 function(i) { return (i.name == field.name) })[0];
419 w.widget.baseWidgetValue(field.widget.widgetValue); // sync widgets
420 w.widget.onload = function(){w.widget.baseWidgetValue(field.widget.widgetValue)}; // async widgets
428 _drawEditDialog : function(storeItem, rowIndex) {
430 var done = function() { self.hideDialog(); };
431 var pane = this._makeEditPane(storeItem, rowIndex, done, done);
432 this.editDialog = new openils.widget.EditDialog({editPane:pane});
433 this.editDialog.startup();
434 this.editDialog.show();
437 showCreateDialog : function() {
439 var done = function() { self.hideDialog(); };
440 var pane = this._makeCreatePane(done, done);
441 this.editDialog = new openils.widget.EditDialog({editPane:pane});
442 this.editDialog.startup();
443 this.editDialog.show();
446 _drawEditPane : function(storeItem, rowIndex) {
448 var done = function() { self.hidePane(); };
449 dojo.style(this.domNode, 'display', 'none');
450 this.editPane = this._makeEditPane(storeItem, rowIndex, done, done);
451 this.editPane.startup();
452 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
453 if(this.onEditPane) this.onEditPane(this.editPane);
456 showClonePane : function() {
458 var done = function() { self.hidePane(); };
459 var row = this.getFirstSelectedRow();
461 dojo.style(this.domNode, 'display', 'none');
462 this.editPane = this._makeClonePane(this.getItem(row), row, done, done);
463 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
464 if(this.onEditPane) this.onEditPane(this.editPane);
467 showCreatePane : function() {
469 var done = function() { self.hidePane(); };
470 dojo.style(this.domNode, 'display', 'none');
471 this.editPane = this._makeCreatePane(done, done);
472 this.editPane.startup();
473 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
474 if(this.onEditPane) this.onEditPane(this.editPane);
477 hideDialog : function() {
478 this.editDialog.hide();
479 this.editDialog.destroy();
480 delete this.editDialog;
484 hidePane : function() {
485 this.domNode.parentNode.removeChild(this.editPane.domNode);
486 this.editPane.destroy();
487 delete this.editPane;
488 dojo.style(this.domNode, 'display', 'block');
492 resetStore : function() {
493 this.setStore(this.buildAutoStore());
496 loadAll : function(opts, search) {
497 dojo.require('openils.PermaCrud');
498 if(this.loadProgressIndicator)
499 dojo.style(this.loadProgressIndicator, 'visibility', 'visible');
502 {limit : this.displayLimit, offset : this.displayOffset},
505 opts = dojo.mixin(opts, {
508 onresponse : function(r) {
509 var item = openils.Util.readResponse(r);
510 self.store.newItem(item.toStoreItem());
512 oncomplete : function() {
513 if(self.loadProgressIndicator)
514 dojo.style(self.loadProgressIndicator, 'visibility', 'hidden');
518 this.cachedQuerySearch = search;
519 this.cachedQueryOpts = opts;
521 new openils.PermaCrud().search(this.fmClass, search, opts);
523 new openils.PermaCrud().retrieveAll(this.fmClass, opts);
528 // static ID generater seed
529 openils.widget.AutoGrid.sequence = 0;
530 openils.widget.AutoGrid.gridCache = {};
532 openils.widget.AutoGrid.markupFactory = dojox.grid.DataGrid.markupFactory;
534 openils.widget.AutoGrid.defaultGetter = function(rowIndex, item) {
536 var val = this.grid.store.getValue(item, this.field);
537 var autoWidget = new openils.widget.AutoFieldWidget({
538 fmClass: this.grid.fmClass,
547 var node = _this.grid.getCell(_this.index).view.getCellNode(rowIndex, _this.index);
549 node.innerHTML = ww.getDisplayString();
554 return autoWidget.getDisplayString();