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 dojo.require('openils.PermaCrud');
7 dojo.requireLocalization("openils.widget", "AutoFieldWidget");
8 var localeStrings = dojo.i18n.getLocalization("openils.widget", "AutoFieldWidget");
10 dojo.declare('openils.widget.AutoFieldWidget', null, {
18 * idlField -- Field description object from fieldmapper.IDL.fmclasses
19 * fmObject -- If available, the object being edited. This will be used
20 * to set the value of the widget.
21 * fmClass -- Class name (not required if idlField or fmObject is set)
22 * fmField -- Field name (not required if idlField)
23 * parentNode -- If defined, the widget will be appended to this DOM node
24 * dijitArgs -- Optional parameters object, passed directly to the dojo widget
25 * orgLimitPerms -- If this field defines a set of org units and an orgLimitPerms
26 * is defined, the code will limit the org units in the set to those
27 * allowed by the permission
29 constructor : function(args) {
33 // find the field description in the IDL if not provided
35 this.fmClass = this.fmObject.classname;
36 this.fmIDL = fieldmapper.IDL.fmclasses[this.fmClass];
39 this.fmIDL = fieldmapper.IDL.fmclasses[this.fmClass];
40 var fields = this.fmIDL.fields;
42 if(fields[f].name == this.fmField)
43 this.idlField = fields[f];
47 throw new Error("AutoFieldWidget could not determine which field to render. We need more information. fmClass=" +
48 this.fmClass + ' fmField=' + this.fmField + ' fmObject=' + js2JSON(this.fmObject));
50 this.auth = openils.User.authtoken;
51 if(!this.cache[this.auth]) {
52 this.cache[this.auth] = {};
57 * Turn the widget-stored value into a value oils understands
59 getFormattedValue : function() {
60 var value = this.baseWidgetValue();
61 switch(this.idlField.datatype) {
63 return (value) ? 't' : 'f'
65 return dojo.date.stamp.toISOString(value);
69 if(isNaN(value)) value = 0;
71 return (value === '') ? null : value;
75 baseWidgetValue : function(value) {
76 var attr = (this.readOnly) ? 'content' : 'value';
77 if(arguments.length) this.widget.attr(attr, value);
78 return this.widget.attr(attr);
82 * Turn the widget-stored value into something visually suitable
84 getDisplayString : function() {
85 var value = this.widgetValue;
86 switch(this.idlField.datatype) {
88 return (openils.Util.isTrue(value)) ? localeStrings.TRUE : localeStrings.FALSE;
90 dojo.require('dojo.date.locale');
91 dojo.require('dojo.date.stamp');
92 var date = dojo.date.stamp.fromISOString(value);
93 return dojo.date.locale.format(date, {formatLength:'short'});
95 if(value === null || value === undefined) return '';
96 return fieldmapper.aou.findOrgUnit(value).shortname();
99 if(isNaN(value)) value = 0;
101 if(value === undefined || value === null)
107 build : function(onload) {
110 // core widget provided for us, attach and move on
111 if(this.parentNode) // may already be in the "right" place
112 this.parentNode.appendChild(this.widget.domNode);
116 if(!this.parentNode) // give it somewhere to live so that dojo won't complain
117 this.parentNode = document.createElement('div');
119 this.onload = onload;
120 if(this.widgetValue == null)
121 this.widgetValue = (this.fmObject) ? this.fmObject[this.idlField.name]() : null;
124 dojo.require('dijit.layout.ContentPane');
125 this.widget = new dijit.layout.ContentPane(this.dijitArgs, this.parentNode);
126 if(this.widgetValue !== null)
127 this._tryLinkedDisplayField();
129 } else if(this.widgetClass) {
130 dojo.require(this.widgetClass);
131 eval('this.widget = new ' + this.widgetClass + '(this.dijitArgs, this.parentNode);');
135 switch(this.idlField.datatype) {
138 dojo.require('dijit.form.TextBox');
139 this.widget = new dijit.form.TextBox(this.dijitArgs, this.parentNode);
143 this._buildOrgSelector();
147 dojo.require('dijit.form.CurrencyTextBox');
148 this.widget = new dijit.form.CurrencyTextBox(this.dijitArgs, this.parentNode);
152 dojo.require('dijit.form.NumberTextBox');
153 this.dijitArgs = dojo.mixin(this.dijitArgs || {}, {constraints:{places:0}});
154 this.widget = new dijit.form.NumberTextBox(this.dijitArgs, this.parentNode);
158 dojo.require('dijit.form.NumberTextBox');
159 this.widget = new dijit.form.NumberTextBox(this.dijitArgs, this.parentNode);
163 dojo.require('dijit.form.DateTextBox');
164 dojo.require('dojo.date.stamp');
165 this.widget = new dijit.form.DateTextBox(this.dijitArgs, this.parentNode);
166 if(this.widgetValue != null)
167 this.widgetValue = dojo.date.stamp.fromISOString(this.widgetValue);
171 dojo.require('dijit.form.CheckBox');
172 this.widget = new dijit.form.CheckBox(this.dijitArgs, this.parentNode);
173 this.widgetValue = openils.Util.isTrue(this.widgetValue);
177 if(this._buildLinkSelector()) break;
180 dojo.require('dijit.form.TextBox');
181 this.widget = new dijit.form.TextBox(this.dijitArgs, this.parentNode);
185 if(!this.async) this._widgetLoaded();
189 // we want to display the value for our widget. However, instead of displaying
190 // an ID, for exmaple, display the value for the 'selector' field on the object
192 _tryLinkedDisplayField : function(noAsync) {
194 if(this.idlField.datatype == 'org_unit')
195 return false; // we already handle org_units, no need to re-fetch
197 var linkInfo = this._getLinkSelector();
198 if(!(linkInfo && linkInfo.vfield && linkInfo.vfield.selector))
200 var lclass = linkInfo.linkClass;
202 if(lclass == 'aou') {
203 this.widgetValue = fieldmapper.aou.findOrgUnit(this.widgetValue).shortname();
207 // first try the store cache
209 if(this.cache[this.auth][lclass]) {
210 var store = this.cache[this.auth][lclass];
212 query[linkInfo.vfield.name] = ''+this.widgetValue;
213 store.fetch({query:query, onComplete:
215 self.widgetValue = store.getValue(list[0], linkInfo.vfield.selector);
221 // then try the single object cache
222 if(this.cacheSingle[lclass] && this.cacheSingle[lclass][this.widgetValue]) {
223 this.widgetValue = this.cacheSingle[lclass][this.widgetValue];
227 // if those fail, fetch the linked object
230 new openils.PermaCrud().retrieve(lclass, this.widgetValue, {
231 async : !this.forceSync,
232 oncomplete : function(r) {
233 var item = openils.Util.readResponse(r);
234 if(!self.cacheSingle[lclass])
235 self.cacheSingle[lclass] = {};
236 self.widgetValue = item[linkInfo.vfield.selector]();
237 self.cacheSingle[lclass][self.widgetValue] = item;
238 self.widget.startup();
239 self._widgetLoaded();
244 _getLinkSelector : function() {
245 var linkClass = this.idlField['class'];
246 if(this.idlField.reltype != 'has_a') return false;
247 if(!fieldmapper.IDL.fmclasses[linkClass].permacrud) return false;
248 if(!fieldmapper.IDL.fmclasses[linkClass].permacrud.retrieve) return false;
251 var rclassIdl = fieldmapper.IDL.fmclasses[linkClass];
253 for(var f in rclassIdl.fields) {
254 if(this.idlField.key == rclassIdl.fields[f].name) {
255 vfield = rclassIdl.fields[f];
261 throw new Error("'" + linkClass + "' has no '" + this.idlField.key + "' field!");
264 linkClass : linkClass,
269 _buildLinkSelector : function() {
270 var selectorInfo = this._getLinkSelector();
271 if(!selectorInfo) return false;
273 var linkClass = selectorInfo.linkClass;
274 var vfield = selectorInfo.vfield;
278 if(linkClass == 'pgt')
279 return this._buildPermGrpSelector();
280 if(linkClass == 'aou')
281 return this._buildOrgSelector();
282 if(linkClass == 'acpl')
283 return this._buildCopyLocSelector();
286 dojo.require('dojo.data.ItemFileReadStore');
287 dojo.require('dijit.form.FilteringSelect');
289 this.widget = new dijit.form.FilteringSelect(this.dijitArgs, this.parentNode);
290 this.widget.searchAttr = this.widget.labelAttr = vfield.selector || vfield.name;
291 this.widget.valueAttr = vfield.name;
294 var oncomplete = function(list) {
297 new dojo.data.ItemFileReadStore({data:fieldmapper[linkClass].toStoreData(list)});
298 self.cache[self.auth][linkClass] = self.widget.store;
300 self.widget.store = self.cache[self.auth][linkClass];
302 self.widget.startup();
303 self._widgetLoaded();
306 if(this.cache[self.auth][linkClass]) {
310 new openils.PermaCrud().retrieveAll(linkClass, {
311 async : !this.forceSync,
312 oncomplete : function(r) {
313 var list = openils.Util.readResponse(r, false, true);
323 * For widgets that run asynchronously, provide a callback for finishing up
325 _widgetLoaded : function(value) {
327 this.baseWidgetValue(this.getDisplayString());
329 this.baseWidgetValue(this.widgetValue);
330 if(this.idlField.name == this.fmIDL.pkey && this.fmIDL.pkey_sequence)
331 this.widget.attr('disabled', true);
332 if(this.disableWidgetTest && this.disableWidgetTest(this.idlField.name, this.fmObject))
333 this.widget.attr('disabled', true);
336 this.onload(this.widget, this);
339 _buildOrgSelector : function() {
340 dojo.require('fieldmapper.OrgUtils');
341 dojo.require('openils.widget.FilteringTreeSelect');
342 this.widget = new openils.widget.FilteringTreeSelect(this.dijitArgs, this.parentNode);
343 this.widget.searchAttr = 'shortname';
344 this.widget.labelAttr = 'shortname';
345 this.widget.parentField = 'parent_ou';
346 var user = new openils.User();
348 if(this.widgetValue == null)
349 this.widgetValue = user.user.ws_ou();
351 // if we have a limit perm, find the relevent orgs (async)
352 if(this.orgLimitPerms && this.orgLimitPerms.length > 0) {
355 user.getPermOrgList(this.orgLimitPerms,
357 self.widget.tree = orgList;
358 self.widget.startup();
359 self._widgetLoaded();
364 this.widget.tree = fieldmapper.aou.globalOrgTree;
365 this.widget.startup();
369 _buildPermGrpSelector : function() {
370 dojo.require('openils.widget.FilteringTreeSelect');
371 this.widget = new openils.widget.FilteringTreeSelect(this.dijitArgs, this.parentNode);
372 this.widget.searchAttr = 'name';
374 if(this.cache.permGrpTree) {
375 this.widget.tree = this.cache.permGrpTree;
376 this.widget.startup();
382 new openils.PermaCrud().retrieveAll('pgt', {
383 async : !this.forceSync,
384 oncomplete : function(r) {
385 var list = openils.Util.readResponse(r, false, true);
390 map[list[l].id()] = list[l];
393 var pnode = map[node.parent()];
394 if(!pnode) {root = node; continue;}
395 if(!pnode.children()) pnode.children([]);
396 pnode.children().push(node);
398 self.widget.tree = self.cache.permGrpTree = root;
399 self.widget.startup();
400 self._widgetLoaded();
407 _buildCopyLocSelector : function() {
408 dojo.require('dijit.form.FilteringSelect');
409 this.widget = new dijit.form.FilteringSelect(this.dijitArgs, this.parentNode);
410 this.widget.searchAttr = this.widget.labalAttr = 'name';
411 this.widget.valueAttr = 'id';
413 if(this.cache.copyLocStore) {
414 this.widget.store = this.cache.copyLocStore;
415 this.widget.startup();
421 var ws_ou = openils.User.user.ws_ou();
422 var orgs = fieldmapper.aou.findOrgUnit(ws_ou).orgNodeTrail().map(function (i) { return i.id() });
423 orgs = orgs.concat(fieldmapper.aou.descendantNodeList(ws_ou).map(function (i) { return i.id() }));
426 new openils.PermaCrud().search('acpl', {owning_lib : orgs}, {
427 async : !this.forceSync,
428 oncomplete : function(r) {
429 var list = openils.Util.readResponse(r, false, true);
432 new dojo.data.ItemFileReadStore({data:fieldmapper.acpl.toStoreData(list)});
433 self.cache.copyLocStore = self.widget.store;
434 self.widget.startup();
435 self._widgetLoaded();