]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/reports/oils_rpt_widget.js
added double-click action to template builder selector items to see details. other...
[Evergreen.git] / Open-ILS / web / reports / oils_rpt_widget.js
1 /* --------------------------------------------------------------------- 
2         Represents a set of values, an inputWidget collects data and a 
3         multi-select displays the data and allows the user to remove items
4         --------------------------------------------------------------------- */
5 function oilsRptSetWidget(args) {
6         this.node = args.node;
7         this.inputWidget = new args.inputWidget(args);
8         this.dest = elem('select',
9                 {multiple:'multiple','class':'oils_rpt_small_info_selector'});
10 }
11
12 oilsRptSetWidget.prototype.draw = function() {
13
14         this.addButton = elem('input',{type:'submit',value:"Add"})
15         this.delButton = elem('input',{type:'submit',value:"Del"})
16
17         var obj = this;
18         this.addButton.onclick = function() {
19                 obj.addDisplayItems(obj.inputWidget.getDisplayValue());
20         }
21
22         this.delButton.onclick = function(){obj.removeSelected()};
23
24         removeChildren(this.node);
25         this.inputWidget.draw();
26         this.node.appendChild(elem('br'))
27         this.node.appendChild(this.addButton);
28         this.node.appendChild(this.delButton);
29         this.node.appendChild(elem('br'))
30         this.node.appendChild(this.dest);
31 }
32
33 oilsRptSetWidget.prototype.addDisplayItems = function(list) {
34         if( list.constructor != Array ) list = [list];
35         for(var i = 0; i < list.length; i++) {
36                 var item = list[i];
37
38                 /* no dupes */
39                 var exists = false;
40                 iterate(this.dest.options, 
41                         function(o){if(o.getAttribute('value') == item.value) {exists = true; return;}});
42                 if(exists) continue;
43
44                 _debug('Inserting SetWidget values ' + js2JSON(item));
45                 insertSelectorVal(this.dest, -1, item.label, this.objToStr(item.value));
46         }
47 }
48
49 oilsRptSetWidget.prototype.removeSelected = function() {
50         oilsDelSelectedItems(this.dest);
51 }
52
53 oilsRptSetWidget.prototype.getValue = function() {
54         var vals = [];
55         var obj = this;
56         iterate(this.dest, function(i){vals.push(obj.strToObj(i.getAttribute('value')))});
57         return vals;
58 }
59
60 oilsRptSetWidget.prototype.objToStr = function(obj) {
61         if( typeof obj == 'string' ) return obj;
62         //return ':'+obj.transform+':'+obj.params[0];
63         var str = ':'+obj.transform;
64         for( var i = 0; i < obj.params.length; i++ ) 
65                 str += ':' + obj.params[i];
66         _debug("objToStr(): built string " + str);
67         return str;
68
69 }
70
71 oilsRptSetWidget.prototype.strToObj = function(str) {
72         if( str.match(/^:.*/) ) {
73                 var parts = str.split(/:/);
74                 _debug("strToObj(): " + str + ' : ' + parts);
75                 parts.shift();
76                 var tform = parts.shift();
77                 //var tform = str.replace(/^:(.*):.*/,'$1');
78                 //var param = str.replace(/^:.*:(.*)/,'$1');
79                 return { transform : tform, params : parts };
80         }
81         return str;
82 }
83
84
85 /* --------------------------------------------------------------------- 
86         represents a widget that has start and end values.  start and end
87         are gathered from start/end widgets
88         --------------------------------------------------------------------- */
89 function oilsRptBetweenWidget(args) {
90         this.node = args.node;
91         this.startWidget = new args.startWidget(args);
92         this.endWidget = new args.endWidget(args);
93 }
94 oilsRptBetweenWidget.prototype.draw = function() {
95         removeChildren(this.node);
96         this.startWidget.draw();
97         this.node.appendChild(elem('hr'));
98         this.node.appendChild(elem('div',
99                 {style:'text-align:center;width:100%;font-weight:bold'},' - And - '));
100         this.node.appendChild(elem('hr'));
101         this.endWidget.draw();
102 }
103 oilsRptBetweenWidget.prototype.getValue = function() {
104         return [
105                 this.startWidget.getValue(),
106                 this.endWidget.getValue()
107         ];
108 }
109
110
111
112
113 /* --------------------------------------------------------------------- 
114         ATOMIC WIDGETS
115         --------------------------------------------------------------------- */
116
117
118 /* --------------------------------------------------------------------- 
119         Atomic text input widget
120         --------------------------------------------------------------------- */
121 function oilsRptTextWidget(args) {
122         this.node = args.node;
123         this.dest = elem('input',{type:'text',size:12});
124         oilsRptMonitorWidget(this.dest);
125 }
126 oilsRptTextWidget.prototype.draw = function() {
127         this.node.appendChild(this.dest);
128 }
129
130 /* returns the "real" value for the widget */
131 oilsRptTextWidget.prototype.getValue = function() {
132         return this.dest.value;
133 }
134
135 /* returns the label and "real" value for the widget */
136 oilsRptTextWidget.prototype.getDisplayValue = function() {
137         return { label : this.getValue(), value : this.getValue() };
138 }
139
140
141
142 /* --------------------------------------------------------------------- 
143         Atomic bool input widget
144         --------------------------------------------------------------------- */
145 function oilsRptBoolWidget(args) {
146         this.node = args.node;
147         this.selector = elem('select');
148         insertSelectorVal(this.selector, -1,'True','t');
149         insertSelectorVal(this.selector, -1,'False','f');
150 }
151
152 oilsRptBoolWidget.prototype.draw = function() {
153         this.node.appendChild(this.selector);
154 }
155
156 /* returns the "real" value for the widget */
157 oilsRptBoolWidget.prototype.getValue = function() {
158         return getSelectorVal(this.selector);
159 }
160
161 /* returns the label and "real" value for the widget */
162 oilsRptBoolWidget.prototype.getDisplayValue = function() {
163         var val = getSelectorVal(this.selector);
164         var label = 'True';
165         if (val == 'f') labal = 'False';
166         return { label : label, value : val };
167 }
168
169
170 /* If you monitor a text widget with this function, it 
171         will style the input differently to indicate the
172         field needs data.  If a regex is provided, it will
173         style the field differently until the data matches 
174         the regex.  The style comes from OILS_RPT_INVALID_DATA. */
175 function oilsRptMonitorWidget(input, regex) {
176         addCSSClass(input, OILS_RPT_INVALID_DATA);
177         var func = function() {
178                 var val = input.value;
179                 if(!val) {
180                         addCSSClass(input, OILS_RPT_INVALID_DATA);
181                 } else {
182                         if( regex ) {
183                                 if( val && val.match(regex) ) 
184                                         removeCSSClass(input, OILS_RPT_INVALID_DATA);
185                                 else
186                                         addCSSClass(input, OILS_RPT_INVALID_DATA);
187                         } else {
188                                 removeCSSClass(input, OILS_RPT_INVALID_DATA);
189                         }
190                 }
191         }
192
193         input.onkeyup = func;
194         input.onchange = func;
195 }
196
197
198
199
200 /* --------------------------------------------------------------------- 
201         Atomic calendar widget
202         --------------------------------------------------------------------- */
203 function oilsRptCalWidget(args) {
204         this.node = args.node;
205         this.calFormat = args.calFormat;
206         this.input = elem('input',{type:'text',size:12});
207
208         oilsRptMonitorWidget(this.input, args.regex);
209
210         if( args.inputSize ) {
211                 this.input.setAttribute('size',args.inputSize);
212                 this.input.setAttribute('maxlength',args.inputSize);
213         }
214 }
215
216 oilsRptCalWidget.prototype.draw = function() {
217         this.button = DOM.generic_calendar_button.cloneNode(true);
218         this.button.id = oilsNextId();
219         this.input.id = oilsNextId();
220
221         this.node.appendChild(this.button);
222         this.node.appendChild(this.input);
223         unHideMe(this.button);
224
225         _debug('making calendar widget with format ' + this.calFormat);
226
227         Calendar.setup({
228                 inputField      : this.input.id,
229                 ifFormat                : this.calFormat,
230                 button          : this.button.id,
231                 align                   : "Tl", 
232                 singleClick     : true
233         });
234 }
235
236 oilsRptCalWidget.prototype.getValue = function() {
237         return this.input.value;
238 }
239
240 oilsRptCalWidget.prototype.getDisplayValue = function() {
241         return { label : this.getValue(), value : this.getValue() };
242 }
243
244
245 /* --------------------------------------------------------------------- 
246         Atomic org widget
247         --------------------------------------------------------------------- */
248 function oilsRptOrgSelector(args) {
249         this.node = args.node;
250         this.selector = elem('select',
251                 {multiple:'multiple','class':'oils_rpt_small_info_selector'});
252 }
253
254 oilsRptOrgSelector.prototype.draw = function(org) {
255         if(!org) org = globalOrgTree;
256         var opt = insertSelectorVal( this.selector, -1, 
257                 org.shortname(), org.id(), null, findOrgDepth(org) );
258         if( org.id() == oilsRptCurrentOrg )
259                 opt.selected = true;
260         
261         /* sometimes we need these choices 
262         if( !isTrue(findOrgType(org.ou_type()).can_have_vols()) )
263                 opt.disabled = true;
264                 */
265
266         if( org.children() ) {
267                 for( var c = 0; c < org.children().length; c++ )
268                         this.draw(org.children()[c]);
269         }
270         this.node.appendChild(this.selector);
271 }
272
273 oilsRptOrgSelector.prototype.getValue = function() {
274         var vals = [];
275         iterate(this.selector, /* XXX this.selector.options?? */
276                 function(o){
277                         if( o.selected )
278                                 vals.push(o.getAttribute('value'))
279                 }
280         );
281         return vals;
282 }
283
284 oilsRptOrgSelector.prototype.getDisplayValue = function() {
285         var vals = [];
286         iterate(this.selector,
287                 function(o){
288                         if( o.selected )
289                                 vals.push({ label : o.innerHTML, value : o.getAttribute('value')});
290                 }
291         );
292         return vals;
293 }
294
295
296 /* --------------------------------------------------------------------- 
297         Atomic age widget
298         --------------------------------------------------------------------- */
299 function oilsRptAgeWidget(args) {
300         this.node = args.node;
301         this.count = elem('select');
302         this.type = elem('select');
303 }
304
305 oilsRptAgeWidget.prototype.draw = function() {
306
307         //insertSelectorVal(this.count, -1, ' -- Select One -- ', '');
308         for( var i = 1; i < 25; i++ )
309                 insertSelectorVal(this.count, -1, i, i);
310
311         //insertSelectorVal(this.type, -1, ' -- Select One -- ', '');
312         insertSelectorVal(this.type, -1, 'Day(s)', 'days');
313         insertSelectorVal(this.type, -1, 'Month(s)', 'months');
314         insertSelectorVal(this.type, -1, 'Year(s)', 'years');
315         this.node.appendChild(this.count);
316         this.node.appendChild(this.type);
317 }
318
319 oilsRptAgeWidget.prototype.getValue = function() {
320         var count = getSelectorVal(this.count);
321         var type = getSelectorVal(this.type);
322         return count+''+type;
323 }
324
325 oilsRptAgeWidget.prototype.getDisplayValue = function() {
326         var val = { value : this.getValue() };
327         var label = getSelectorVal(this.count) + ' ';
328         for( var i = 0; i < this.type.options.length; i++ ) {
329                 var opt = this.type.options[i];
330                 if( opt.selected )
331                         label += opt.innerHTML;
332         }
333         val.label = label;
334         return val;
335 }
336
337
338
339 /* --------------------------------------------------------------------- 
340         Atomic substring picker
341         --------------------------------------------------------------------- */
342 function oilsRptSubstrWidget(args) {
343         this.node = args.node
344         this.data = elem('input',{type:'text',size:12})
345         this.offset = elem('input',{type:'text',size:5})
346         this.length = elem('input',{type:'text',size:5})
347 }
348
349 oilsRptSubstrWidget.prototype.draw = function() {
350         this.node.appendChild(text('string: '))
351         this.node.appendChild(this.data);
352         this.node.appendChild(elem('br'));
353         this.node.appendChild(text('offset: '))
354         this.node.appendChild(this.offset);
355         this.node.appendChild(elem('br'));
356         this.node.appendChild(text('length: '))
357         this.node.appendChild(this.length);
358 }
359
360 oilsRptSubstrWidget.prototype.getValue = function() {
361         return {
362                 transform : 'substring',
363                 params : [ this.data.value, this.offset.value, this.length.value ]
364         };
365 }
366
367 oilsRptSubstrWidget.prototype.getDisplayValue = function() {
368         return {
369                 label : this.data.value + ' : ' + this.offset.value + ' : ' + this.length.value,
370                 value : this.getValue()
371         };
372 }
373
374
375 /* --------------------------------------------------------------------- 
376         Atomic number picker
377         --------------------------------------------------------------------- */
378 function oilsRptNumberWidget(args) {
379         this.node = args.node;
380         this.size = args.size || 32;
381         this.start = args.start;
382         this.selector = elem('select');
383 }
384 oilsRptNumberWidget.prototype.draw = function() {
385         //insertSelectorVal(this.selector, -1, ' -- Select One -- ', '');
386         for( var i = this.start; i < (this.size + this.start); i++ )
387                 insertSelectorVal(this.selector, -1, i, i);
388         this.node.appendChild(this.selector);
389         var obj = this;
390 }
391
392 oilsRptNumberWidget.prototype.getValue = function() {
393         return getSelectorVal(this.selector);
394 }
395
396 oilsRptNumberWidget.prototype.getDisplayValue = function() {
397         return { label : this.getValue(), value : this.getValue() };
398 }
399
400
401 /* --------------------------------------------------------------------- 
402         Relative dates widget
403         --------------------------------------------------------------------- */
404 function oilsRptTruncPicker(args) {
405         this.node = args.node;
406         this.type = args.type;
407         this.realSpan = elem('span');
408         this.relSpan = elem('span');
409         hideMe(this.relSpan);
410         args.node = this.realSpan;
411         this.calWidget = new oilsRptCalWidget(args);
412         args.node = this.node;
413
414         this.selector = elem('select');
415         insertSelectorVal(this.selector,-1,'Real Date',1);
416         insertSelectorVal(this.selector,-1,'Relative Date',2);
417
418         this.numberPicker = 
419                 new oilsRptNumberWidget({node:this.relSpan,size:90,start:1});
420
421         this.label = 'Day(s)';
422         if(this.type == 'month') this.label = 'Month(s)';
423         if(this.type == 'quarter') this.label = 'Quarter(s)';
424         if(this.type == 'year') this.label = 'Year(s)';
425         if(this.type == 'date') this.label = 'Day(s)';
426 }
427
428 oilsRptTruncPicker.prototype.draw = function() {
429         this.node.appendChild(this.selector);
430         this.node.appendChild(this.realSpan);
431         this.node.appendChild(this.relSpan);
432         this.calWidget.draw();
433         this.numberPicker.draw();
434         this.relSpan.appendChild(text(this.label+' ago'));
435
436         var obj = this;
437         this.selector.onchange = function() {
438                 if( getSelectorVal(obj.selector) == 1 ) {
439                         unHideMe(obj.realSpan);
440                         hideMe(obj.relSpan);
441                 } else {
442                         unHideMe(obj.relSpan);
443                         hideMe(obj.realSpan);
444                 }
445         }
446 }
447
448 oilsRptTruncPicker.prototype.getValue = function() {
449         if( getSelectorVal(this.selector) == 2) {
450                 var val = this.numberPicker.getValue();
451                 var tform = 'relative_' + this.type;
452                 return { transform : tform, params : ['-'+val] };
453         }
454         return this.calWidget.getValue();
455 }
456
457 oilsRptTruncPicker.prototype.getDisplayValue = function() {
458         if( getSelectorVal(this.selector) == 2) {
459                 var num = this.numberPicker.getValue();
460                 return { label : num +' '+this.label+' ago', value : this.getValue() };
461         }
462         return this.calWidget.getDisplayValue();
463 }
464
465
466 /* --------------------------------------------------------------------- 
467         Atomic remote object picker
468         --------------------------------------------------------------------- */
469
470 function oilsRptRemoteWidget(args) {
471         this.node       = args.node;
472         this.class      = args.class;
473         this.field      = args.field;
474         this.column = args.column;
475         this.source = elem('select',
476                 {multiple:'multiple','class':'oils_rpt_small_info_selector'});
477 }
478
479 oilsRptRemoteWidget.prototype.draw = function() {
480         var orgcol;
481         iterate(oilsIDL[this.class].fields,
482                 function(i) {
483                         if(i.type == 'link' && i.class == 'aou') 
484                                 orgcol = i.name;
485                 }
486         );
487
488         if(orgcol) _debug("found org column for remote widget: " + orgcol);
489
490         var orgs = [];
491         iterate(oilsRptMyOrgs,function(i){orgs.push(i.id());});
492         var req = new Request(OILS_RPT_MAGIC_FETCH, SESSION, {
493                 hint:this.class,
494                 org_column : orgcol,
495                 org : orgs
496         }); 
497
498         var obj = this;
499         this.node.appendChild(this.source);
500         req.callback(function(r){obj.render(r.getResultObject())});
501         req.send();
502 }
503
504 oilsRptRemoteWidget.prototype.render = function(objs) {
505         for( var i = 0; i < objs.length; i++ ) {
506                 var obj = objs[i];
507                 var label = obj[this.field.selector]();
508                 var value = obj[this.column]();
509                 _debug("inserted remote object "+label + ' : ' + value);
510                 insertSelectorVal(this.source, -1, label, value);
511         }
512 }
513
514 oilsRptRemoteWidget.prototype.getDisplayValue = function() {
515         var vals = [];
516         iterate(this.source,
517                 function(o){
518                         if( o.selected )
519                                 vals.push({ label : o.innerHTML, value : o.getAttribute('value')});
520                 }
521         );
522         return vals;
523 }
524
525 oilsRptRemoteWidget.prototype.getValue = function() {
526         var vals = [];
527         iterate(this.source,
528                 function(o){
529                         if( o.selected )
530                                 vals.push(o.getAttribute('value'))
531                 }
532         );
533         return vals;
534 }
535
536
537
538
539 /* --------------------------------------------------------------------- 
540         CUSTOM WIDGETS
541         --------------------------------------------------------------------- */
542
543 /* --------------------------------------------------------------------- 
544         custom my-orgs picker 
545         --------------------------------------------------------------------- */
546 function oilsRptMyOrgsWidget(node, orgid, maxorg) {
547         _debug('fetching my orgs with max org of ' + maxorg);
548         this.node = node;
549         this.orgid = orgid;
550         this.maxorg = maxorg || 1;
551         this.active = true;
552         if( maxorg < 1 ) {
553                 this.node.disabled = true;
554                 this.active = false;
555         }
556 }
557
558 oilsRptMyOrgsWidget.prototype.draw = function() {
559         if(!oilsRptMyOrgs) {
560                 var req = new Request(OILS_RPT_FETCH_ORG_FULL_PATH, this.orgid);
561                 var obj = this;
562                 req.callback(
563                         function(r) { obj.drawWidget(r.getResultObject()); }
564                 );
565                 req.send();
566         } else {
567                 this.drawWidget(oilsRptMyOrgs);
568         }
569 }
570
571 oilsRptMyOrgsWidget.prototype.drawWidget = function(orglist) {
572         var sel = this.node;
573         var started = false;
574         oilsRptMyOrgs = orglist;
575         for( var i = 0; i < orglist.length; i++ ) {
576                 var org = orglist[i];
577                 var opt = insertSelectorVal( this.node, -1, 
578                         org.name(), org.id(), null, findOrgDepth(org) );
579                 if( org.id() == this.orgid )
580                         opt.selected = true;
581                 if(!started) {
582                         if( org.id() == this.maxorg ) 
583                                 started = true;
584                         else opt.disabled = true;
585                 }
586         }
587 }
588
589 oilsRptMyOrgsWidget.prototype.getValue = function() {
590         return getSelectorVal(this.node);
591 }
592
593