]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/dojo/openils/widget/AutoFieldWidget.js
don't assume org unit value is non-null
[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             new openils.PermaCrud().retrieveAll(linkClass, {   
207                 async : true,
208                 oncomplete : function(r) {
209                     var list = openils.Util.readResponse(r, false, true);
210                     if(list) {
211                         self.widget.store = 
212                             new dojo.data.ItemFileReadStore({data:fieldmapper[linkClass].toStoreData(list)});
213                     }
214                     self.widget.startup();
215                     self._widgetLoaded();
216                 }
217             });
218
219             return true;
220         },
221
222         /**
223          * For widgets that run asynchronously, provide a callback for finishing up
224          */
225         _widgetLoaded : function(value) {
226             if(this.readOnly) {
227                 this.baseWidgetValue(this.getDisplayString());
228             } else {
229                 this.baseWidgetValue(this.widgetValue);
230                 if(this.idlField.name == this.fmIDL.pkey && this.fmIDL.pkey_sequence)
231                     this.widget.attr('disabled', true); 
232             }
233             if(this.onload)
234                 this.onload(this.widget, self);
235         },
236
237         _buildOrgSelector : function() {
238             dojo.require('fieldmapper.OrgUtils');
239             dojo.require('openils.widget.FilteringTreeSelect');
240             this.widget = new openils.widget.FilteringTreeSelect(this.dijitArgs, this.parentNode);
241             this.widget.searchAttr = 'shortname';
242             this.widget.labelAttr = 'shortname';
243             this.widget.parentField = 'parent_ou';
244             
245             // if we have a limit perm, find the relevent orgs (async)
246             if(this.orgLimitPerms && this.orgLimitPerms.length > 0) {
247                 this.async = true;
248                 var user = new openils.User();
249                 var self = this;
250                 user.getPermOrgList(this.orgLimitPerms, 
251                     function(orgList) {
252                         self.widget.tree = orgList;
253                         self.widget.startup();
254                         self._widgetLoaded();
255                     }
256                 );
257
258             } else {
259                 this.widget.tree = fieldmapper.aou.globalOrgTree;
260                 this.widget.startup();
261             }
262         },
263
264         _buildPermGrpSelector : function() {
265             dojo.require('openils.widget.FilteringTreeSelect');
266             this.widget = new openils.widget.FilteringTreeSelect(this.dijitArgs, this.parentNode);
267             this.widget.searchAttr = 'name';
268
269             if(this.cache.permGrpTree) {
270                 this.widget.tree = this.cache.permGrpTree;
271                 this.widget.startup();
272                 return;
273             } 
274
275             var self = this;
276             this.async = true;
277             new openils.PermaCrud().retrieveAll('pgt', {
278                 async : true,
279                 oncomplete : function(r) {
280                     var list = openils.Util.readResponse(r, false, true);
281                     if(!list) return;
282                     var map = {};
283                     var root = null;
284                     for(var l in list)
285                         map[list[l].id()] = list[l];
286                     for(var l in list) {
287                         var node = list[l];
288                         var pnode = map[node.parent()];
289                         if(!pnode) {root = node; continue;}
290                         if(!pnode.children()) pnode.children([]);
291                         pnode.children().push(node);
292                     }
293                     self.widget.tree = self.cache.permGrpTree = root;
294                     self.widget.startup();
295                     self._widgetLoaded();
296                 }
297             });
298
299             return true;
300         }
301     });
302 }
303