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.widget.GridColumnPicker');
9 dojo.require('openils.Util');
12 'openils.widget.AutoGrid',
13 [dojox.grid.DataGrid, openils.widget.AutoWidget],
16 /* if true, pop up an edit dialog when user hits Enter on a give row */
18 defaultCellWidth : null,
20 suppressFields : null,
22 selectorWidth : '1.5',
23 showColumnPicker : false,
24 columnPickerPrefix : null,
26 /* by default, don't show auto-generated (sequence) fields */
27 showSequenceFields : false,
29 startup : function() {
30 this.selectionMode = 'single';
31 this.sequence = openils.widget.AutoGrid.sequence++;
32 openils.widget.AutoGrid.gridCache[this.sequence] = this;
33 this.inherited(arguments);
35 this.attr('structure', this._compileStructure());
36 this.setStore(this.buildAutoStore());
38 if(this.showColumnPicker) {
39 if(!this.columnPickerPrefix) {
40 console.error("No columnPickerPrefix defined");
42 var picker = new openils.widget.GridColumnPicker(
43 openils.User.authtoken, this.columnPickerPrefix, this);
44 if(openils.User.authtoken) {
47 openils.Util.addOnLoad(function() { picker.load() });
52 this.overrideEditWidgets = {};
53 this.overrideEditWidgetClass = {};
56 this._applyEditOnEnter();
57 else if(this.singleEditStyle)
58 this._applySingleEditStyle();
60 if(!this.hideSelector) {
61 dojo.connect(this, 'onHeaderCellClick',
64 this.toggleSelectAll();
70 /* Don't allow sorting on the selector column */
71 canSort : function(rowIdx) {
72 if(rowIdx == 1 && !this.hideSelector)
77 _compileStructure : function() {
78 var existing = (this.structure && this.structure[0].cells[0]) ?
79 this.structure[0].cells[0] : [];
83 function pushEntry(entry) {
84 if(self.suppressFields) {
85 if(dojo.indexOf(self.suppressFields, entry.field) != -1)
89 entry.get = openils.widget.AutoGrid.defaultGetter
90 if(!entry.width && self.defaultCellWidth)
91 entry.width = self.defaultCellWidth;
95 if(!this.hideSelector) {
96 // insert the selector column
99 formatter : function(rowIdx) { return self._formatRowSelectInput(rowIdx); },
100 get : function(rowIdx, item) { if(item) return rowIdx; },
101 width : this.selectorWidth,
108 if(!this.fieldOrder) {
109 /* no order defined, start with any explicit grid fields */
110 for(var e in existing) {
111 var entry = existing[e];
112 var field = this.fmIDL.fields.filter(
113 function(i){return (i.name == entry.field)})[0];
114 if(field) entry.name = entry.name || field.label;
119 for(var f in this.sortedFieldList) {
120 var field = this.sortedFieldList[f];
121 if(!field || field.virtual) continue;
123 // field was already added above
124 if(fields.filter(function(i){return (i.field == field.name)})[0])
127 var entry = existing.filter(function(i){return (i.field == field.name)})[0];
129 entry.name = field.label;
131 // unless specifically requested, hide sequence fields
132 if(!this.showSequenceFields && field.name == this.fmIDL.pkey && this.fmIDL.pkey_sequence)
135 entry = {field:field.name, name:field.label};
140 if(this.fieldOrder) {
141 /* append any explicit non-IDL grid fields to the end */
142 for(var e in existing) {
143 var entry = existing[e];
144 var field = fields.filter(
145 function(i){return (i.field == entry.field)})[0];
146 if(field) continue; // don't duplicate
151 return [{cells: [fields]}];
154 toggleSelectAll : function() {
155 var selected = this.getSelectedRows();
156 for(var i = 0; i < this.rowCount; i++) {
164 getSelectedRows : function() {
167 dojo.query('[name=autogrid.selector]', this.domNode),
170 rows.push(input.getAttribute('row'));
176 getFirstSelectedRow : function() {
177 return this.getSelectedRows()[0];
180 getSelectedItems : function() {
183 dojo.forEach(this.getSelectedRows(), function(idx) { items.push(self.getItem(idx)); });
187 selectRow : function(rowIdx) {
188 var inputs = dojo.query('[name=autogrid.selector]', this.domNode);
189 for(var i = 0; i < inputs.length; i++) {
190 if(inputs[i].getAttribute('row') == rowIdx) {
191 if(!inputs[i].disabled)
192 inputs[i].checked = true;
198 deSelectRow : function(rowIdx) {
199 var inputs = dojo.query('[name=autogrid.selector]', this.domNode);
200 for(var i = 0; i < inputs.length; i++) {
201 if(inputs[i].getAttribute('row') == rowIdx) {
202 inputs[i].checked = false;
208 getAllObjects : function() {
212 onComplete : function(list) {
215 objs.push(new fieldmapper[self.fmClass]().fromStoreItem(item));
223 deleteSelected : function() {
224 var items = this.getSelectedItems();
225 var total = items.length;
227 dojo.require('openils.PermaCrud');
228 var pcrud = new openils.PermaCrud();
231 var fmObject = new fieldmapper[self.fmClass]().fromStoreItem(item);
232 pcrud['delete'](fmObject, {oncomplete : function(r) { self.store.deleteItem(item) }});
237 _formatRowSelectInput : function(rowIdx) {
238 if(rowIdx === null || rowIdx === undefined) return '';
239 var s = "<input type='checkbox' name='autogrid.selector' row='" + rowIdx + "'";
240 if(this.disableSelectorForRow && this.disableSelectorForRow(rowIdx))
241 s += " disabled='disabled'";
245 _applySingleEditStyle : function() {
246 this.onMouseOverRow = function(e) {};
247 this.onMouseOutRow = function(e) {};
248 this.onCellFocus = function(cell, rowIndex) {
249 this.selection.deselectAll();
250 this.selection.select(this.focus.rowIndex);
254 /* capture keydown and launch edit dialog on enter */
255 _applyEditOnEnter : function() {
256 this._applySingleEditStyle();
258 dojo.connect(this, 'onRowDblClick',
260 if(this.editStyle == 'pane')
261 this._drawEditPane(this.selection.getFirstSelected(), this.focus.rowIndex);
263 this._drawEditDialog(this.selection.getFirstSelected(), this.focus.rowIndex);
267 dojo.connect(this, 'onKeyDown',
269 if(e.keyCode == dojo.keys.ENTER) {
270 this.selection.deselectAll();
271 this.selection.select(this.focus.rowIndex);
272 if(this.editStyle == 'pane')
273 this._drawEditPane(this.selection.getFirstSelected(), this.focus.rowIndex);
275 this._drawEditDialog(this.selection.getFirstSelected(), this.focus.rowIndex);
281 _makeEditPane : function(storeItem, rowIndex, onPostSubmit, onCancel) {
283 var fmObject = new fieldmapper[this.fmClass]().fromStoreItem(storeItem);
284 var idents = grid.store.getIdentityAttributes();
286 var pane = new openils.widget.EditPane({
288 overrideWidgets : this.overrideEditWidgets,
289 overrideWidgetClass : this.overrideEditWidgetClass,
290 disableWidgetTest : this.disableWidgetTest,
291 onPostSubmit : function() {
292 for(var i in fmObject._fields) {
293 var field = fmObject._fields[i];
294 if(idents.filter(function(j){return (j == field)})[0])
295 continue; // don't try to edit an identifier field
296 grid.store.setValue(storeItem, field, fmObject[field]());
298 if(self.onPostUpdate)
299 self.onPostUpdate(storeItem, rowIndex);
303 grid.views.views[0].getCellNode(rowIndex, 0).focus();
307 if(onPostSubmit) onPostSubmit();
309 onCancel : function() {
310 setTimeout(function(){
311 grid.views.views[0].getCellNode(rowIndex, 0).focus();},200);
312 if(onCancel) onCancel();
316 pane.fieldOrder = this.fieldOrder;
317 pane.mode = 'update';
321 _makeCreatePane : function(onPostSubmit, onCancel) {
323 var pane = new openils.widget.EditPane({
324 fmClass : this.fmClass,
325 overrideWidgets : this.overrideEditWidgets,
326 overrideWidgetClass : this.overrideEditWidgetClass,
327 disableWidgetTest : this.disableWidgetTest,
328 onPostSubmit : function(r) {
329 var fmObject = openils.Util.readResponse(r);
330 if(grid.onPostCreate)
331 grid.onPostCreate(fmObject);
333 grid.store.newItem(fmObject.toStoreItem());
334 setTimeout(function(){
336 grid.selection.select(grid.rowCount-1);
337 grid.views.views[0].getCellNode(grid.rowCount-1, 1).focus();
343 onCancel : function() {
344 if(onCancel) onCancel();
347 pane.fieldOrder = this.fieldOrder;
348 pane.mode = 'create';
352 // .startup() is called within
353 _makeClonePane : function(storeItem, rowIndex, onPostSubmit, onCancel) {
354 var clonePane = this._makeCreatePane(onPostSubmit, onCancel);
355 var origPane = this._makeEditPane(storeItem, rowIndex);
358 dojo.forEach(origPane.fieldList,
360 if(field.widget.widget.attr('disabled')) return;
361 var w = clonePane.fieldList.filter(
362 function(i) { return (i.name == field.name) })[0];
363 w.widget.baseWidgetValue(field.widget.widgetValue); // sync widgets
364 w.widget.onload = function(){w.widget.baseWidgetValue(field.widget.widgetValue)}; // async widgets
372 _drawEditDialog : function(storeItem, rowIndex) {
374 var done = function() { self.hideDialog(); };
375 var pane = this._makeEditPane(storeItem, rowIndex, done, done);
376 this.editDialog = new openils.widget.EditDialog({editPane:pane});
377 this.editDialog.startup();
378 this.editDialog.show();
381 showCreateDialog : function() {
383 var done = function() { self.hideDialog(); };
384 var pane = this._makeCreatePane(done, done);
385 this.editDialog = new openils.widget.EditDialog({editPane:pane});
386 this.editDialog.startup();
387 this.editDialog.show();
390 _drawEditPane : function(storeItem, rowIndex) {
392 var done = function() { self.hidePane(); };
393 dojo.style(this.domNode, 'display', 'none');
394 this.editPane = this._makeEditPane(storeItem, rowIndex, done, done);
395 this.editPane.startup();
396 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
397 if(this.onEditPane) this.onEditPane(this.editPane);
400 showClonePane : function() {
402 var done = function() { self.hidePane(); };
403 var row = this.getFirstSelectedRow();
405 dojo.style(this.domNode, 'display', 'none');
406 this.editPane = this._makeClonePane(this.getItem(row), row, done, done);
407 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
408 if(this.onEditPane) this.onEditPane(this.editPane);
411 showCreatePane : function() {
413 var done = function() { self.hidePane(); };
414 dojo.style(this.domNode, 'display', 'none');
415 this.editPane = this._makeCreatePane(done, done);
416 this.editPane.startup();
417 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
418 if(this.onEditPane) this.onEditPane(this.editPane);
421 hideDialog : function() {
422 this.editDialog.hide();
423 this.editDialog.destroy();
424 delete this.editDialog;
428 hidePane : function() {
429 this.domNode.parentNode.removeChild(this.editPane.domNode);
430 this.editPane.destroy();
431 delete this.editPane;
432 dojo.style(this.domNode, 'display', 'block');
436 resetStore : function() {
437 this.setStore(this.buildAutoStore());
440 loadAll : function(opts, search) {
441 dojo.require('openils.PermaCrud');
444 opts = dojo.mixin(opts, {
447 onresponse : function(r) {
448 var item = openils.Util.readResponse(r);
449 self.store.newItem(item.toStoreItem());
453 new openils.PermaCrud().search(this.fmClass, search, opts);
455 new openils.PermaCrud().retrieveAll(this.fmClass, opts);
460 // static ID generater seed
461 openils.widget.AutoGrid.sequence = 0;
462 openils.widget.AutoGrid.gridCache = {};
464 openils.widget.AutoGrid.markupFactory = dojox.grid.DataGrid.markupFactory;
466 openils.widget.AutoGrid.defaultGetter = function(rowIndex, item) {
468 var val = this.grid.store.getValue(item, this.field);
469 var autoWidget = new openils.widget.AutoFieldWidget({
470 fmClass: this.grid.fmClass,
476 //autoWidget.build();
477 return autoWidget.getDisplayString();