]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js
added some user sesssion and object-list caching
[working/Evergreen.git] / Open-ILS / web / js / dojo / openils / widget / AutoFieldWidget.js
1 if(!dojo._hasResource['openils.widget.AutoFieldWidget']) {
2     dojo.provide('openils.widget.AutoFieldWidget');
3     dojo.require('openils.Util');
4     dojo.require('openils.User');
5     dojo.require('fieldmapper.IDL');
6
7     dojo.declare('openils.widget.AutoFieldWidget', null, {
8
9         async : false,
10         cache : {},
11
12         /**
13          * args:
14          *  idlField -- Field description object from fieldmapper.IDL.fmclasses
15          *  fmObject -- If available, the object being edited.  This will be used 
16          *      to set the value of the widget.
17          *  fmClass -- Class name (not required if idlField or fmObject is set)
18          *  fmField -- Field name (not required if idlField)
19          *  parentNode -- If defined, the widget will be appended to this DOM node
20          *  dijitArgs -- Optional parameters object, passed directly to the dojo widget
21          *  orgLimitPerms -- If this field defines a set of org units and an orgLimitPerms 
22          *      is defined, the code will limit the org units in the set to those
23          *      allowed by the permission
24          */
25         constructor : function(args) {
26             for(var k in args)
27                 this[k] = args[k];
28
29             // find the field description in the IDL if not provided
30             if(this.fmObject) 
31                 this.fmClass = this.fmObject.classname;
32             this.fmIDL = fieldmapper.IDL.fmclasses[this.fmClass];
33
34             if(!this.idlField) {
35                 this.fmIDL = fieldmapper.IDL.fmclasses[this.fmClass];
36                 var fields = this.fmIDL.fields;
37                 for(var f in fields) 
38                     if(fields[f].name == this.fmField)
39                         this.idlField = fields[f];
40             }
41         },
42
43         /**
44          * Turn the widget-stored value into a value oils understands
45          */
46         getFormattedValue : function() {
47             var value = this.baseWidgetValue();
48             switch(this.idlField.datatype) {
49                 case 'bool':
50                     return (value) ? 't' : 'f'
51                 case 'timestamp':
52                     return dojo.date.stamp.toISOString(value);
53                 case 'int':
54                 case 'float':
55                     if(isNaN(value)) value = 0;
56                 default:
57                     return (value === '') ? null : value;
58             }
59         },
60
61         baseWidgetValue : function(value) {
62             var attr = (this.readOnly) ? 'content' : 'value';
63             if(arguments.length) this.widget.attr(attr, value);
64             return this.widget.attr(attr);
65         },
66         
67         /**
68          * Turn the widget-stored value into something visually suitable
69          */
70         getDisplayString : function() {
71             var value = this.widgetValue;
72             switch(this.idlField.datatype) {
73                 case 'bool':
74                     return (value) ? 'True' : 'False'; // XXX i18n!
75                 case 'timestamp':
76                     dojo.require('dojo.date.locale');
77                     dojo.require('dojo.date.stamp');
78                     var date = dojo.date.stamp.fromISOString(value);
79                     return dojo.date.locale.format(date, {formatLength:'short'});
80                 case 'org_unit':
81                     if(value === null || value === undefined) return '';
82                     return fieldmapper.aou.findOrgUnit(value).shortname();
83                 case 'int':
84                 case 'float':
85                     if(isNaN(value)) value = 0;
86                 default:
87                     if(value === undefined || value === null)
88                         value = '';
89                     return value+'';
90             }
91         },
92
93         build : function(onload) {
94
95             if(this.widget) {
96                 // core widget provided for us, attach and move on
97                 if(this.parentNode) // may already be in the "right" place
98                     this.parentNode.appendChild(this.widget.domNode);
99                 return;
100             }
101
102             this.onload = onload;
103             if(this.widgetValue == null)
104                 this.widgetValue = (this.fmObject) ? this.fmObject[this.idlField.name]() : null;
105
106             if(this.readOnly) {
107                 dojo.require('dijit.layout.ContentPane');
108                 this.widget = new dijit.layout.ContentPane(this.dijitArgs, this.parentNode);
109
110             } else if(this.widgetClass) {
111                 dojo.require(this.widgetClass);
112                 eval('this.widget = new ' + this.widgetClass + '(this.dijitArgs, this.parentNode);');
113
114             } else {
115
116                 switch(this.idlField.datatype) {
117                     
118                     case 'id':
119                         dojo.require('dijit.form.TextBox');
120                         this.widget = new dijit.form.TextBox(this.dijitArgs, this.parentNode);
121                         this.widget.attr('disabled', true); // never allow editing of IDs
122                         break;
123
124                     case 'org_unit':
125                         this._buildOrgSelector();
126                         break;
127
128                     case 'money':
129                         dojo.require('dijit.form.CurrencyTextBox');
130                         this.widget = new dijit.form.CurrencyTextBox(this.dijitArgs, this.parentNode);
131                         break;
132
133                     case 'int':
134                         dojo.require('dijit.form.NumberTextBox');
135                         this.dijitArgs = dojo.mixin(this.dijitArgs || {}, {constraints:{places:0}});
136                         this.widget = new dijit.form.NumberTextBox(this.dijitArgs, this.parentNode);
137                         break;
138
139                     case 'float':
140                         dojo.require('dijit.form.NumberTextBox');
141                         this.widget = new dijit.form.NumberTextBox(this.dijitArgs, this.parentNode);
142                         break;
143
144                     case 'timestamp':
145                         dojo.require('dijit.form.DateTextBox');
146                         dojo.require('dojo.date.stamp');
147                         this.widget = new dijit.form.DateTextBox(this.dijitArgs, this.parentNode);
148                         if(this.widgetValue != null) 
149                             this.widgetValue = dojo.date.stamp.fromISOString(this.widgetValue);
150                         break;
151
152                     case 'bool':
153                         dojo.require('dijit.form.CheckBox');
154                         this.widget = new dijit.form.CheckBox(this.dijitArgs, this.parentNode);
155                         this.widgetValue = openils.Util.isTrue(this.widgetValue);
156                         break;
157
158                     case 'link':
159                         if(this._buildLinkSelector()) break;
160
161                     default:
162                         dojo.require('dijit.form.TextBox');
163                         this.widget = new dijit.form.TextBox(this.dijitArgs, this.parentNode);
164                 }
165             }
166
167             if(!this.async) this._widgetLoaded();
168             return this.widget;
169         },
170
171         _buildLinkSelector : function() {
172
173             /* verify we can and should grab the related class */
174             var linkClass = this.idlField['class'];
175             if(this.idlField.reltype != 'has_a')  return false;
176             if(!fieldmapper.IDL.fmclasses[linkClass].permacrud) return false;
177             if(!fieldmapper.IDL.fmclasses[linkClass].permacrud.retrieve) return false;
178
179             dojo.require('openils.PermaCrud');
180             dojo.require('dojo.data.ItemFileReadStore');
181             dojo.require('dijit.form.FilteringSelect');
182
183             var self = this;
184             var vfield;
185             var rclassIdl = fieldmapper.IDL.fmclasses[linkClass];
186
187             if(linkClass == 'pgt')
188                 return self._buildPermGrpSelector();
189
190             this.async = true;
191             this.widget = new dijit.form.FilteringSelect(this.dijitArgs, this.parentNode);
192
193             for(var f in rclassIdl.fields) {
194                 if(self.idlField.key == rclassIdl.fields[f].name) {
195                     vfield = rclassIdl.fields[f];
196                     break;
197                 }
198             }
199
200             if(!vfield) 
201                 throw new Error("'" + linkClass + "' has no '" + self.idlField.key + "' field!");
202
203             this.widget.searchAttr = this.widget.labelAttr = vfield.selector || vfield.name;
204             this.widget.valueAttr = vfield.name;
205
206             var oncomplete = function(list) {
207                 if(list) {
208                     self.widget.store = 
209                         new dojo.data.ItemFileReadStore({data:fieldmapper[linkClass].toStoreData(list)});
210                     self.cache[linkClass] = list;
211                 }
212                 self.widget.startup();
213                 self._widgetLoaded();
214             };
215
216             if(this.cache[linkClass]) {
217                 oncomplete(this.cache[linkClass]);
218
219             } else {
220                 new openils.PermaCrud().retrieveAll(linkClass, {   
221                     async : true,
222                     oncomplete : function(r) {
223                         var list = openils.Util.readResponse(r, false, true);
224                         oncomplete(list);
225                     }
226                 });
227             }
228
229             return true;
230         },
231
232         /**
233          * For widgets that run asynchronously, provide a callback for finishing up
234          */
235         _widgetLoaded : function(value) {
236             if(this.readOnly) {
237                 this.baseWidgetValue(this.getDisplayString());
238             } else {
239                 this.baseWidgetValue(this.widgetValue);
240                 if(this.idlField.name == this.fmIDL.pkey && this.fmIDL.pkey_sequence)
241                     this.widget.attr('disabled', true); 
242             }
243             if(this.onload)
244                 this.onload(this.widget, self);
245         },
246
247         _buildOrgSelector : function() {
248             dojo.require('fieldmapper.OrgUtils');
249             dojo.require('openils.widget.FilteringTreeSelect');
250             this.widget = new openils.widget.FilteringTreeSelect(this.dijitArgs, this.parentNode);
251             this.widget.searchAttr = 'shortname';
252             this.widget.labelAttr = 'shortname';
253             this.widget.parentField = 'parent_ou';
254             
255             // if we have a limit perm, find the relevent orgs (async)
256             if(this.orgLimitPerms && this.orgLimitPerms.length > 0) {
257                 this.async = true;
258                 var user = new openils.User();
259                 var self = this;
260                 user.getPermOrgList(this.orgLimitPerms, 
261                     function(orgList) {
262                         self.widget.tree = orgList;
263                         self.widget.startup();
264                         self._widgetLoaded();
265                     }
266                 );
267
268             } else {
269                 this.widget.tree = fieldmapper.aou.globalOrgTree;
270                 this.widget.startup();
271             }
272         },
273
274         _buildPermGrpSelector : function() {
275             dojo.require('openils.widget.FilteringTreeSelect');
276             this.widget = new openils.widget.FilteringTreeSelect(this.dijitArgs, this.parentNode);
277             this.widget.searchAttr = 'name';
278
279             if(this.cache.permGrpTree) {
280                 this.widget.tree = this.cache.permGrpTree;
281                 this.widget.startup();
282                 return;
283             } 
284
285             var self = this;
286             this.async = true;
287             new openils.PermaCrud().retrieveAll('pgt', {
288                 async : true,
289                 oncomplete : function(r) {
290                     var list = openils.Util.readResponse(r, false, true);
291                     if(!list) return;
292                     var map = {};
293                     var root = null;
294                     for(var l in list)
295                         map[list[l].id()] = list[l];
296                     for(var l in list) {
297                         var node = list[l];
298                         var pnode = map[node.parent()];
299                         if(!pnode) {root = node; continue;}
300                         if(!pnode.children()) pnode.children([]);
301                         pnode.children().push(node);
302                     }
303                     self.widget.tree = self.cache.permGrpTree = root;
304                     self.widget.startup();
305                     self._widgetLoaded();
306                 }
307             });
308
309             return true;
310         }
311     });
312 }
313