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');
11 'openils.widget.AutoGrid',
12 [dojox.grid.DataGrid, openils.widget.AutoWidget],
15 /* if true, pop up an edit dialog when user hits Enter on a give row */
17 defaultCellWidth : null,
19 suppressFields : null,
21 selectorWidth : '1.5',
23 /* by default, don't show auto-generated (sequence) fields */
24 showSequenceFields : false,
26 startup : function() {
27 this.selectionMode = 'single';
28 this.inherited(arguments);
30 this.setStructure(this._compileStructure());
31 this.setStore(this.buildAutoStore());
32 this.overrideEditWidgets = {};
33 this.overrideEditWidgetClass = {};
35 this._applyEditOnEnter();
36 else if(this.singleEditStyle)
37 this._applySingleEditStyle();
38 this.sequence = openils.widget.AutoGrid.sequence++;
39 openils.widget.AutoGrid.gridCache[this.sequence] = this;
42 _compileStructure : function() {
43 var existing = (this.structure && this.structure[0].cells[0]) ?
44 this.structure[0].cells[0] : [];
48 function pushEntry(entry) {
49 if(self.suppressFields) {
50 if(dojo.indexOf(self.suppressFields, entry.field) != -1)
54 entry.get = openils.widget.AutoGrid.defaultGetter
55 if(!entry.width && self.defaultCellWidth)
56 entry.width = self.defaultCellWidth;
60 if(!this.hideSelector) {
61 // insert the selector column
64 get : function(rowIdx, item) { return self._buildRowSelectInput(rowIdx, item); },
65 width : this.selectorWidth,
70 if(!this.fieldOrder) {
71 /* no order defined, start with any explicit grid fields */
72 for(var e in existing) {
73 var entry = existing[e];
74 var field = this.fmIDL.fields.filter(
75 function(i){return (i.name == entry.field)})[0];
76 if(field) entry.name = entry.name || field.label;
81 for(var f in this.sortedFieldList) {
82 var field = this.sortedFieldList[f];
83 if(!field || field.virtual) continue;
85 // field was already added above
86 if(fields.filter(function(i){return (i.field == field.name)})[0])
89 if(!this.showSequenceFields && field.name == this.fmIDL.pkey && this.fmIDL.pkey_sequence)
91 var entry = existing.filter(function(i){return (i.field == field.name)})[0];
92 if(entry) entry.name = field.label;
93 else entry = {field:field.name, name:field.label};
98 /* append any explicit non-IDL grid fields to the end */
99 for(var e in existing) {
100 var entry = existing[e];
101 var field = fields.filter(
102 function(i){return (i.field == entry.field)})[0];
103 if(field) continue; // don't duplicate
108 return [{cells: [fields]}];
111 getSelectedRows : function() {
112 var rows = []; dojo.forEach(
113 dojo.query('[name=autogrid.selector]', this.domNode),
116 rows.push(input.getAttribute('row'));
122 getFirstSelectedRow : function() {
123 return this.getSelectedRows()[0];
126 getSelectedItems : function() {
129 dojo.forEach(this.getSelectedRows(), function(idx) { items.push(self.getItem(idx)); });
133 selectRow : function(rowIdx) {
134 var inputs = dojo.query('[name=autogrid.selector]', this.domNode);
135 for(var i = 0; i < inputs.length; i++) {
136 if(inputs[i].getAttribute('row') == rowIdx) {
137 inputs[i].checked = true;
143 deSelectRow : function(rowIdx) {
144 var inputs = dojo.query('[name=autogrid.selector]', this.domNode);
145 for(var i = 0; i < inputs.length; i++) {
146 if(inputs[i].getAttribute('row') == rowIdx) {
147 inputs[i].checked = false;
153 deleteSelected : function() {
154 var items = this.getSelectedItems();
155 var total = items.length;
157 dojo.require('openils.PermaCrud');
158 var pcrud = new openils.PermaCrud();
161 var fmObject = new fieldmapper[self.fmClass]().fromStoreItem(item);
162 pcrud['delete'](fmObject, {oncomplete : function(r) { self.store.deleteItem(item) }});
167 _buildRowSelectInput : function(rowIdx, item) {
169 return "<input type='checkbox' name='autogrid.selector' row='" + rowIdx + "'/>";
172 _applySingleEditStyle : function() {
173 this.onMouseOverRow = function(e) {};
174 this.onMouseOutRow = function(e) {};
175 this.onCellFocus = function(cell, rowIndex) {
176 this.selection.deselectAll();
177 this.selection.select(this.focus.rowIndex);
181 /* capture keydown and launch edit dialog on enter */
182 _applyEditOnEnter : function() {
183 this._applySingleEditStyle();
185 dojo.connect(this, 'onRowDblClick',
187 if(this.editStyle == 'pane')
188 this._drawEditPane(this.selection.getFirstSelected(), this.focus.rowIndex);
190 this._drawEditDialog(this.selection.getFirstSelected(), this.focus.rowIndex);
194 dojo.connect(this, 'onKeyDown',
196 if(dojo.keys.UP_ARROW) {
197 console.log("up arrow");
198 console.log(this.getSelectedRows() + ' : ' + this.focus.rowIndex);
200 if(e.keyCode == dojo.keys.ENTER) {
201 this.selection.deselectAll();
202 this.selection.select(this.focus.rowIndex);
203 if(this.editStyle == 'pane')
204 this._drawEditPane(this.selection.getFirstSelected(), this.focus.rowIndex);
206 this._drawEditDialog(this.selection.getFirstSelected(), this.focus.rowIndex);
212 _makeEditPane : function(storeItem, rowIndex, onPostSubmit, onCancel) {
214 var fmObject = new fieldmapper[this.fmClass]().fromStoreItem(storeItem);
215 var idents = grid.store.getIdentityAttributes();
217 var pane = new openils.widget.EditPane({
219 overrideWidgets : this.overrideEditWidgets,
220 overrideWidgetClass : this.overrideEditWidgetClass,
221 disableWidgetTest : this.disableWidgetTest,
222 onPostSubmit : function() {
223 for(var i in fmObject._fields) {
224 var field = fmObject._fields[i];
225 if(idents.filter(function(j){return (j == field)})[0])
226 continue; // don't try to edit an identifier field
227 grid.store.setValue(storeItem, field, fmObject[field]());
229 if(self.onPostUpdate)
230 self.onPostUpdate(storeItem, rowIndex);
234 grid.views.views[0].getCellNode(rowIndex, 0).focus();
238 if(onPostSubmit) onPostSubmit();
240 onCancel : function() {
241 setTimeout(function(){
242 grid.views.views[0].getCellNode(rowIndex, 0).focus();},200);
243 if(onCancel) onCancel();
247 pane.fieldOrder = this.fieldOrder;
248 pane.mode = 'update';
252 _makeCreatePane : function(onPostSubmit, onCancel) {
254 var pane = new openils.widget.EditPane({
255 fmClass : this.fmClass,
256 overrideWidgets : this.overrideEditWidgets,
257 overrideWidgetClass : this.overrideEditWidgetClass,
258 disableWidgetTest : this.disableWidgetTest,
259 onPostSubmit : function(r) {
260 var fmObject = openils.Util.readResponse(r);
262 grid.store.newItem(fmObject.toStoreItem());
263 if(grid.onPostCreate)
264 grid.onPostCreate(fmObject);
265 setTimeout(function(){
267 grid.selection.select(grid.rowCount-1);
268 grid.views.views[0].getCellNode(grid.rowCount-1, 1).focus();
274 onCancel : function() {
275 if(onCancel) onCancel();
278 pane.fieldOrder = this.fieldOrder;
279 pane.mode = 'create';
283 // .startup() is called within
284 _makeClonePane : function(storeItem, rowIndex, onPostSubmit, onCancel) {
285 var clonePane = this._makeCreatePane(onPostSubmit, onCancel);
286 var origPane = this._makeEditPane(storeItem, rowIndex);
289 dojo.forEach(origPane.fieldList,
291 if(field.widget.widget.attr('disabled')) return;
292 var w = clonePane.fieldList.filter(
293 function(i) { return (i.name == field.name) })[0];
294 w.widget.baseWidgetValue(field.widget.widgetValue); // sync widgets
295 w.widget.onload = function(){w.widget.baseWidgetValue(field.widget.widgetValue)}; // async widgets
303 _drawEditDialog : function(storeItem, rowIndex) {
305 var done = function() { self.hideDialog(); };
306 var pane = this._makeEditPane(storeItem, rowIndex, done, done);
307 this.editDialog = new openils.widget.EditDialog({editPane:pane});
308 this.editDialog.startup();
309 this.editDialog.show();
312 showCreateDialog : function() {
314 var done = function() { self.hideDialog(); };
315 var pane = this._makeCreatePane(done, done);
316 this.editDialog = new openils.widget.EditDialog({editPane:pane});
317 this.editDialog.startup();
318 this.editDialog.show();
321 _drawEditPane : function(storeItem, rowIndex) {
323 var done = function() { self.hidePane(); };
324 dojo.style(this.domNode, 'display', 'none');
325 this.editPane = this._makeEditPane(storeItem, rowIndex, done, done);
326 this.editPane.startup();
327 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
330 showClonePane : function() {
332 var done = function() { self.hidePane(); };
333 var row = this.getFirstSelectedRow();
335 dojo.style(this.domNode, 'display', 'none');
336 this.editPane = this._makeClonePane(this.getItem(row), row, done, done);
337 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
340 showCreatePane : function() {
342 var done = function() { self.hidePane(); };
343 dojo.style(this.domNode, 'display', 'none');
344 this.editPane = this._makeCreatePane(done, done);
345 this.editPane.startup();
346 this.domNode.parentNode.insertBefore(this.editPane.domNode, this.domNode);
349 hideDialog : function() {
350 this.editDialog.hide();
351 this.editDialog.destroy();
352 delete this.editDialog;
355 hidePane : function() {
356 this.domNode.parentNode.removeChild(this.editPane.domNode);
357 this.editPane.destroy();
358 delete this.editPane;
359 dojo.style(this.domNode, 'display', 'block');
363 resetStore : function() {
364 this.setStore(this.buildAutoStore());
367 loadAll : function(opts, search) {
368 dojo.require('openils.PermaCrud');
371 opts = dojo.mixin(opts, {
374 onresponse : function(r) {
375 var item = openils.Util.readResponse(r);
376 self.store.newItem(item.toStoreItem());
380 new openils.PermaCrud().search(this.fmClass, search, opts);
382 new openils.PermaCrud().retrieveAll(this.fmClass, opts);
387 // static ID generater seed
388 openils.widget.AutoGrid.sequence = 0;
389 openils.widget.AutoGrid.gridCache = {};
391 openils.widget.AutoGrid.markupFactory = dojox.grid.DataGrid.markupFactory;
393 openils.widget.AutoGrid.defaultGetter = function(rowIndex, item) {
395 var val = this.grid.store.getValue(item, this.field);
396 var autoWidget = new openils.widget.AutoFieldWidget({
397 fmClass: this.grid.fmClass,
401 return autoWidget.getDisplayString();