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());
42 if(this.showColumnPicker) {
43 if(!this.columnPickerPrefix) {
44 console.error("No columnPickerPrefix defined");
46 var picker = new openils.widget.GridColumnPicker(
47 openils.User.authtoken, this.columnPickerPrefix, this);
48 if(openils.User.authtoken) {
51 openils.Util.addOnLoad(function() { picker.load() });
56 this.overrideEditWidgets = {};
57 this.overrideEditWidgetClass = {};
60 this._applyEditOnEnter();
61 else if(this.singleEditStyle)
62 this._applySingleEditStyle();
64 if(!this.hideSelector) {
65 dojo.connect(this, 'onHeaderCellClick',
68 this.toggleSelectAll();
73 if(this.showPaginator) {
75 this.paginator = new dijit.layout.ContentPane();
78 var back = dojo.create('a', {
80 style : 'padding-right:6px;',
81 href : 'javascript:void(0);',
82 onclick : function() {
84 self.cachedQueryOpts.offset = self.displayOffset -= self.displayLimit;
85 self.loadAll(self.cachedQueryOpts, self.cachedQuerySearch);
89 var forw = dojo.create('a', {
91 style : 'padding-right:6px;',
92 href : 'javascript:void(0);',
93 onclick : function() {
95 self.cachedQueryOpts.offset = self.displayOffset += self.displayLimit;
96 self.loadAll(self.cachedQueryOpts, self.cachedQuerySearch);
100 dojo.place(this.paginator.domNode, this.domNode, 'before');
101 dojo.place(back, this.paginator.domNode);
102 dojo.place(forw, this.paginator.domNode);
103 this.loadProgressIndicator = dojo.create('img', {
104 src:'/opac/images/progressbar_green.gif',
105 style:'height:16px;width:16px;'
107 dojo.place(this.loadProgressIndicator, this.paginator.domNode);
111 /* Don't allow sorting on the selector column */
112 canSort : function(rowIdx) {
113 if(rowIdx == 1 && !this.hideSelector)
118 _compileStructure : function() {
119 var existing = (this.structure && this.structure[0].cells[0]) ?
120 this.structure[0].cells[0] : [];
124 function pushEntry(entry) {
125 if(self.suppressFields) {
126 if(dojo.indexOf(self.suppressFields, entry.field) != -1)
130 entry.get = openils.widget.AutoGrid.defaultGetter
131 if(!entry.width && self.defaultCellWidth)
132 entry.width = self.defaultCellWidth;
136 if(!this.hideSelector) {
137 // insert the selector column
140 formatter : function(rowIdx) { return self._formatRowSelectInput(rowIdx); },
141 get : function(rowIdx, item) { if(item) return rowIdx; },
142 width : this.selectorWidth,
149 if(!this.fieldOrder) {
150 /* no order defined, start with any explicit grid fields */
151 for(var e in existing) {
152 var entry = existing[e];
153 var field = this.fmIDL.fields.filter(
154 function(i){return (i.name == entry.field)})[0];
155 if(field) entry.name = entry.name || field.label;
160 for(var f in this.sortedFieldList) {
161 var field = this.sortedFieldList[f];
162 if(!field || field.virtual) continue;
164 // field was already added above
165 if(fields.filter(function(i){return (i.field == field.name)})[0])
168 var entry = existing.filter(function(i){return (i.field == field.name)})[0];
170 entry.name = field.label;
172 // unless specifically requested, hide sequence fields
173 if(!this.showSequenceFields && field.name == this.fmIDL.pkey && this.fmIDL.pkey_sequence)
176 entry = {field:field.name, name:field.label};
181 if(this.fieldOrder) {
182 /* append any explicit non-IDL grid fields to the end */
183 for(var e in existing) {
184 var entry = existing[e];
185 var field = fields.filter(
186 function(i){return (i.field == entry.field)})[0];
187 if(field) continue; // don't duplicate
192 return [{cells: [fields]}];
195 toggleSelectAll : function() {
196 var selected = this.getSelectedRows();
197 for(var i = 0; i < this.rowCount; i++) {
205 getSelectedRows : function() {
208 dojo.query('[name=autogrid.selector]', this.domNode),
211 rows.push(input.getAttribute('row'));
217 getFirstSelectedRow : function() {
218 return this.getSelectedRows()[0];
221 getSelectedItems : function() {
224 dojo.forEach(this.getSelectedRows(), function(idx) { items.push(self.getItem(idx)); });
228 selectRow : function(rowIdx) {
229 var inputs = dojo.query('[name=autogrid.selector]', this.domNode);
230 for(var i = 0; i < inputs.length; i++) {
231 if(inputs[i].getAttribute('row') == rowIdx) {
232 if(!inputs[i].disabled)
233 inputs[i].checked = true;
239 deSelectRow : function(rowIdx) {
240 var inputs = dojo.query('[name=autogrid.selector]', this.domNode);
241 for(var i = 0; i < inputs.length; i++) {
242 if(inputs[i].getAttribute('row') == rowIdx) {
243 inputs[i].checked = false;
249 getAllObjects : function() {
253 onComplete : function(list) {
256 objs.push(new fieldmapper[self.fmClass]().fromStoreItem(item));
264 deleteSelected : function() {
265 var items = this.getSelectedItems();
266 var total = items.length;
268 dojo.require('openils.PermaCrud');
269 var pcrud = new openils.PermaCrud();
272 var fmObject = new fieldmapper[self.fmClass]().fromStoreItem(item);
273 pcrud['delete'](fmObject, {oncomplete : function(r) { self.store.deleteItem(item) }});
278 _formatRowSelectInput : function(rowIdx) {
279 if(rowIdx === null || rowIdx === undefined) return '';
280 var s = "<input type='checkbox' name='autogrid.selector' row='" + rowIdx + "'";
281 if(this.disableSelectorForRow && this.disableSelectorForRow(rowIdx))
282 s += " disabled='disabled'";
286 _applySingleEditStyle : function() {
287 this.onMouseOverRow = function(e) {};
288 this.onMouseOutRow = function(e) {};
289 this.onCellFocus = function(cell, rowIndex) {
290 this.selection.deselectAll();
291 this.selection.select(this.focus.rowIndex);
295 /* capture keydown and launch edit dialog on enter */
296 _applyEditOnEnter : function() {
297 this._applySingleEditStyle();
299 dojo.connect(this, 'onRowDblClick',
301 if(this.editStyle == 'pane')
302 this._drawEditPane(this.selection.getFirstSelected(), this.focus.rowIndex);
304 this._drawEditDialog(this.selection.getFirstSelected(), this.focus.rowIndex);
308 dojo.connect(this, 'onKeyDown',
310 if(e.keyCode == dojo.keys.ENTER) {
311 this.selection.deselectAll();
312 this.selection.select(this.focus.rowIndex);
313 if(this.editStyle == 'pane')
314 this._drawEditPane(this.selection.getFirstSelected(), this.focus.rowIndex);
316 this._drawEditDialog(this.selection.getFirstSelected(), this.focus.rowIndex);
322 _makeEditPane : function(storeItem, rowIndex, onPostSubmit, onCancel) {
324 var fmObject = new fieldmapper[this.fmClass]().fromStoreItem(storeItem);
325 var idents = grid.store.getIdentityAttributes();
327 var pane = new openils.widget.EditPane({
329 overrideWidgets : this.overrideEditWidgets,
330 overrideWidgetClass : this.overrideEditWidgetClass,
331 disableWidgetTest : this.disableWidgetTest,
332 onPostSubmit : function() {
333 for(var i in fmObject._fields) {
334 var field = fmObject._fields[i];
335 if(idents.filter(function(j){return (j == field)})[0])
336 continue; // don't try to edit an identifier field
337 grid.store.setValue(storeItem, field, fmObject[field]());
339 if(self.onPostUpdate)
340 self.onPostUpdate(storeItem, rowIndex);
344 grid.views.views[0].getCellNode(rowIndex, 0).focus();
348 if(onPostSubmit) onPostSubmit();
350 onCancel : function() {
351 setTimeout(function(){
352 grid.views.views[0].getCellNode(rowIndex, 0).focus();},200);
353 if(onCancel) onCancel();
357 pane.fieldOrder = this.fieldOrder;
358 pane.mode = 'update';
362 _makeCreatePane : function(onPostSubmit, onCancel) {
364 var pane = new openils.widget.EditPane({
365 fmClass : this.fmClass,
366 overrideWidgets : this.overrideEditWidgets,
367 overrideWidgetClass : this.overrideEditWidgetClass,
368 disableWidgetTest : this.disableWidgetTest,
369 onPostSubmit : function(r) {
370 var fmObject = openils.Util.readResponse(r);
371 if(grid.onPostCreate)
372 grid.onPostCreate(fmObject);
374 grid.store.newItem(fmObject.toStoreItem());
375 setTimeout(function(){
377 grid.selection.select(grid.rowCount-1);
378 grid.views.views[0].getCellNode(grid.rowCount-1, 1).focus();
384 onCancel : function() {
385 if(onCancel) onCancel();
388 pane.fieldOrder = this.fieldOrder;
389 pane.mode = 'create';
393 // .startup() is called within
394 _makeClonePane : function(storeItem, rowIndex, onPostSubmit, onCancel) {
395 var clonePane = this._makeCreatePane(onPostSubmit, onCancel);
396 var origPane = this._makeEditPane(storeItem, rowIndex);
399 dojo.forEach(origPane.fieldList,
401 if(field.widget.widget.attr('disabled')) return;
402 var w = clonePane.fieldList.filter(
403 function(i) { return (i.name == field.name) })[0];
404 w.widget.baseWidgetValue(field.widget.widgetValue); // sync widgets
405 w.widget.onload = function(){w.widget.baseWidgetValue(field.widget.widgetValue)}; // async widgets
413 _drawEditDialog : function(storeItem, rowIndex) {
415 var done = function() { self.hideDialog(); };
416 var pane = this._makeEditPane(storeItem, rowIndex, done, done);
417 this.editDialog = new openils.widget.EditDialog({editPane:pane});
418 this.editDialog.startup();
419 this.editDialog.show();
422 showCreateDialog : function() {
424 var done = function() { self.hideDialog(); };
425 var pane = this._makeCreatePane(done, done);
426 this.editDialog = new openils.widget.EditDialog({editPane:pane});
427 this.editDialog.startup();
428 this.editDialog.show();
431 _drawEditPane : function(storeItem, rowIndex) {
433 var done = function() { self.hidePane(); };
434 dojo.style(this.domNode, 'display', 'none');
435 this.editPane = this._makeEditPane(storeItem, rowIndex, done, done);
436 this.editPane.startup();
437 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
438 if(this.onEditPane) this.onEditPane(this.editPane);
441 showClonePane : function() {
443 var done = function() { self.hidePane(); };
444 var row = this.getFirstSelectedRow();
446 dojo.style(this.domNode, 'display', 'none');
447 this.editPane = this._makeClonePane(this.getItem(row), row, done, done);
448 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
449 if(this.onEditPane) this.onEditPane(this.editPane);
452 showCreatePane : function() {
454 var done = function() { self.hidePane(); };
455 dojo.style(this.domNode, 'display', 'none');
456 this.editPane = this._makeCreatePane(done, done);
457 this.editPane.startup();
458 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
459 if(this.onEditPane) this.onEditPane(this.editPane);
462 hideDialog : function() {
463 this.editDialog.hide();
464 this.editDialog.destroy();
465 delete this.editDialog;
469 hidePane : function() {
470 this.domNode.parentNode.removeChild(this.editPane.domNode);
471 this.editPane.destroy();
472 delete this.editPane;
473 dojo.style(this.domNode, 'display', 'block');
477 resetStore : function() {
478 this.setStore(this.buildAutoStore());
481 loadAll : function(opts, search) {
482 dojo.require('openils.PermaCrud');
483 if(this.loadProgressIndicator)
484 dojo.style(this.loadProgressIndicator, 'visibility', 'visible');
487 {limit : this.displayLimit, offset : this.displayOffset},
490 opts = dojo.mixin(opts, {
493 onresponse : function(r) {
494 var item = openils.Util.readResponse(r);
495 self.store.newItem(item.toStoreItem());
497 oncomplete : function() {
498 if(self.loadProgressIndicator)
499 dojo.style(self.loadProgressIndicator, 'visibility', 'hidden');
503 this.cachedQuerySearch = search;
504 this.cachedQueryOpts = opts;
506 new openils.PermaCrud().search(this.fmClass, search, opts);
508 new openils.PermaCrud().retrieveAll(this.fmClass, opts);
513 // static ID generater seed
514 openils.widget.AutoGrid.sequence = 0;
515 openils.widget.AutoGrid.gridCache = {};
517 openils.widget.AutoGrid.markupFactory = dojox.grid.DataGrid.markupFactory;
519 openils.widget.AutoGrid.defaultGetter = function(rowIndex, item) {
521 var val = this.grid.store.getValue(item, this.field);
522 var autoWidget = new openils.widget.AutoFieldWidget({
523 fmClass: this.grid.fmClass,
532 var node = _this.grid.getCell(_this.index).view.getCellNode(rowIndex, _this.index);
534 node.innerHTML = ww.getDisplayString();
539 return autoWidget.getDisplayString();